<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>記事一覧 on ポンコツ地方エンジニアの技術ブログ</title><link>https://blog.ponkotools.com/posts/</link><description>Recent content in 記事一覧 on ポンコツ地方エンジニアの技術ブログ</description><generator>Hugo -- gohugo.io</generator><language>ja-jp</language><lastBuildDate>Wed, 22 Jul 2026 00:00:00 +0900</lastBuildDate><atom:link href="https://blog.ponkotools.com/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Cloudflare Pages に Web Analytics を導入する</title><link>https://blog.ponkotools.com/posts/2026/07/22/cloudflare-web-analytics/</link><pubDate>Wed, 22 Jul 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/07/22/cloudflare-web-analytics/</guid><description>&lt;p&gt;Cloudflare Dashboard で、&lt;strong&gt;Workers &amp;amp; Pages&lt;/strong&gt; を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="133px" data-flex-grow="55" height="515" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/07/22/cloudflare-web-analytics/01.webp" width="287"&gt;&lt;/p&gt;
&lt;p&gt;対象の Pages プロジェクトを選択した後、&lt;strong&gt;Metrics&lt;/strong&gt; タブを選択し、ページ下部にある &lt;strong&gt;Web Analytics → Enable&lt;/strong&gt; をクリックします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="374px" data-flex-grow="156" height="671" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/07/22/cloudflare-web-analytics/02.webp" srcset="https://blog.ponkotools.com/posts/2026/07/22/cloudflare-web-analytics/02_hu_486265102ddf48d9.webp 800w, https://blog.ponkotools.com/posts/2026/07/22/cloudflare-web-analytics/02.webp 1048w" width="1048"&gt;&lt;/p&gt;
&lt;p&gt;これで OK です。&lt;/p&gt;</description></item><item><title>Cloudflare Web Analytics を導入する</title><link>https://blog.ponkotools.com/posts/2026/07/21/cloudflare-web-analytics/</link><pubDate>Tue, 21 Jul 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/07/21/cloudflare-web-analytics/</guid><description>&lt;p&gt;Cloudflare を経由していないサイトの場合の設定方法です。&lt;/p&gt;
&lt;h2 id="cloudflare-web-analytics-にサイトを追加"&gt;&lt;a href="#cloudflare-web-analytics-%e3%81%ab%e3%82%b5%e3%82%a4%e3%83%88%e3%82%92%e8%bf%bd%e5%8a%a0" class="header-anchor"&gt;&lt;/a&gt;Cloudflare Web Analytics にサイトを追加
&lt;/h2&gt;&lt;p&gt;Cloudflare Dashboard で、 &lt;strong&gt;Analytics &amp;gt; Web Analytics&lt;/strong&gt; と進みます。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="153px" data-flex-grow="63" height="462" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/07/21/cloudflare-web-analytics/01.webp" width="295"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Add a site&lt;/strong&gt; をクリックします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="596px" data-flex-grow="248" height="279" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/07/21/cloudflare-web-analytics/02.webp" width="694"&gt;&lt;/p&gt;
&lt;p&gt;ホスト名を入力し、&lt;strong&gt;Done&lt;/strong&gt; をクリックします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="735px" data-flex-grow="306" height="342" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/07/21/cloudflare-web-analytics/03.webp" srcset="https://blog.ponkotools.com/posts/2026/07/21/cloudflare-web-analytics/03_hu_a03d9074e905677f.webp 800w, https://blog.ponkotools.com/posts/2026/07/21/cloudflare-web-analytics/03.webp 1048w" width="1048"&gt;&lt;/p&gt;
&lt;p&gt;Cloudflare を経由していないサイトの場合、登録後に JavaScript snippet が表示されるのでコピーします。&lt;/p&gt;
&lt;p&gt;このスニペットを、通常は &lt;/body&gt; の直前などに入れます。&lt;/p&gt;</description></item><item><title>VS Code での Git Worktree の使い方</title><link>https://blog.ponkotools.com/posts/2026/07/13/git-worktree/</link><pubDate>Mon, 13 Jul 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/07/13/git-worktree/</guid><description>&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 22.04&lt;/li&gt;
&lt;li&gt;Visual Studio Code 1.128.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="事前準備"&gt;&lt;a href="#%e4%ba%8b%e5%89%8d%e6%ba%96%e5%82%99" class="header-anchor"&gt;&lt;/a&gt;事前準備
&lt;/h2&gt;&lt;p&gt;VS Code の設定で、&lt;code&gt;git.detectWorktrees&lt;/code&gt; を ON にします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="415px" data-flex-grow="173" height="409" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/07/13/git-worktree/01.webp" width="708"&gt;&lt;/p&gt;
&lt;p&gt;ワークツリーの作成だけなら OFF の状態でもできましたが、ワークツリーを切り替えたり削除したりするには ON にする必要がありました。&lt;/p&gt;
&lt;h2 id="ワークツリーの作成"&gt;&lt;a href="#%e3%83%af%e3%83%bc%e3%82%af%e3%83%84%e3%83%aa%e3%83%bc%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;ワークツリーの作成
&lt;/h2&gt;&lt;p&gt;ソース管理タブのリポジトリ横のメニューから作成できます。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="335px" data-flex-grow="139" height="512" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/07/13/git-worktree/02.webp" width="716"&gt;&lt;/p&gt;
&lt;p&gt;ブランチの作成と、フォルダの場所を入力します。&lt;br&gt;
デフォルトでは以下のようなフォルダ構成になります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;リポジトリ名
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;リポジトリ名.worktrees
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── ブランチ名
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ワークツリーが作成されたのが確認できます。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="266px" data-flex-grow="110" height="420" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/07/13/git-worktree/03.webp" width="466"&gt;&lt;/p&gt;
&lt;h2 id="ワークツリーを作業ツリーで開く"&gt;&lt;a href="#%e3%83%af%e3%83%bc%e3%82%af%e3%83%84%e3%83%aa%e3%83%bc%e3%82%92%e4%bd%9c%e6%a5%ad%e3%83%84%e3%83%aa%e3%83%bc%e3%81%a7%e9%96%8b%e3%81%8f" class="header-anchor"&gt;&lt;/a&gt;ワークツリーを作業ツリーで開く
&lt;/h2&gt;&lt;p&gt;作成したワークツリー横のメニューから「現在のウィンドウで作業ツリーを開く」または「新しいウィンドウで作業ツリーを開く」を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="345px" data-flex-grow="144" height="545" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/07/13/git-worktree/04.webp" width="785"&gt;&lt;/p&gt;
&lt;p&gt;あとはいつも通り変更してコミットなどを行います。&lt;/p&gt;
&lt;h2 id="ワークツリーの削除"&gt;&lt;a href="#%e3%83%af%e3%83%bc%e3%82%af%e3%83%84%e3%83%aa%e3%83%bc%e3%81%ae%e5%89%8a%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;ワークツリーの削除
&lt;/h2&gt;&lt;p&gt;ソース管理タブのリポジトリにて、ワークツリー横のメニューから作成できます。&lt;br&gt;
（右クリックからでもいけます）&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="345px" data-flex-grow="144" height="545" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/07/13/git-worktree/05.webp" width="785"&gt;&lt;/p&gt;
&lt;p&gt;該当のワークツリーを作業ツリーで開いている場合は削除できませんので、その場合はメインリポジトリに切り替えてから削除する必要があります。&lt;/p&gt;</description></item><item><title>Ubuntu で Orca を使う</title><link>https://blog.ponkotools.com/posts/2026/07/12/orca/</link><pubDate>Sun, 12 Jul 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/07/12/orca/</guid><description>&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 24.04&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ダウンロード"&gt;&lt;a href="#%e3%83%80%e3%82%a6%e3%83%b3%e3%83%ad%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;ダウンロード
&lt;/h2&gt;&lt;p&gt;以下から Linux 用の AppImage をダウンロードします。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.onorca.dev/" target="_blank" rel="noopener"
 &gt;https://www.onorca.dev/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="実行手順"&gt;&lt;a href="#%e5%ae%9f%e8%a1%8c%e6%89%8b%e9%a0%86" class="header-anchor"&gt;&lt;/a&gt;実行手順
&lt;/h2&gt;&lt;p&gt;実行権限を与えて実行するだけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x orca-linux.AppImage
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./orca-linux.AppImage
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="エラーがでた場合"&gt;&lt;a href="#%e3%82%a8%e3%83%a9%e3%83%bc%e3%81%8c%e3%81%a7%e3%81%9f%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;エラーがでた場合
&lt;/h2&gt;&lt;p&gt;私の環境では以下のエラーが出ました。&lt;/p&gt;
&lt;h3 id="libfuse2-がない"&gt;&lt;a href="#libfuse2-%e3%81%8c%e3%81%aa%e3%81%84" class="header-anchor"&gt;&lt;/a&gt;libfuse2 がない
&lt;/h3&gt;&lt;p&gt;エラー内容は以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dlopen&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;loading&lt;/span&gt; &lt;span class="n"&gt;libfuse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;so&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AppImages&lt;/span&gt; &lt;span class="n"&gt;require&lt;/span&gt; &lt;span class="n"&gt;FUSE&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;You&lt;/span&gt; &lt;span class="n"&gt;might&lt;/span&gt; &lt;span class="n"&gt;still&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;able&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;extract&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;contents&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;AppImage&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;appimage&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;extract&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;See&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;AppImage&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;AppImageKit&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;wiki&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;FUSE&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;information&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;libfuse2&lt;/code&gt; が必要みたいなので、以下で追加しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo add-apt-repository universe
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install libfuse2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="chrome-sandbox-の権限エラー"&gt;&lt;a href="#chrome-sandbox-%e3%81%ae%e6%a8%a9%e9%99%90%e3%82%a8%e3%83%a9%e3%83%bc" class="header-anchor"&gt;&lt;/a&gt;chrome-sandbox の権限エラー
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[40727:0718/110452.982911:FATAL:sandbox/linux/suid/client/setuid_sandbox_host.cc:166] The SUID sandbox helper binary was found, but is not configured correctly. Rather than run without sandboxing I&amp;#39;m aborting now. You need to make sure that /tmp/.mount_orca-lhdNQH6/chrome-sandbox is owned by root and has mode 4755.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Trace/breakpoint trap (コアダンプ)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;--no-sandbox&lt;/code&gt; をつければとりあえず起動できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./orca-linux.AppImage --no-sandbox
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="原因"&gt;&lt;a href="#%e5%8e%9f%e5%9b%a0" class="header-anchor"&gt;&lt;/a&gt;原因
&lt;/h4&gt;&lt;p&gt;Electron製のOrcaは、内部のChromiumプロセスを隔離するため、Linuxでは主に次のいずれかのsandbox方式を使います。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;user namespace sandbox&lt;/strong&gt;
一般ユーザー権限のままLinux namespaceを作成する方式&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SUID sandbox&lt;/strong&gt;
&lt;code&gt;chrome-sandbox&lt;/code&gt; をroot所有・権限&lt;code&gt;4755&lt;/code&gt;で実行する方式&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ubuntu 22.04では1のuser namespace方式がそのまま利用できたため、AppImage内のchrome-sandboxがSUID設定されていなくても起動できました。&lt;/p&gt;
&lt;p&gt;Ubuntu 24.04ではAppArmorによる以下の制限が既定で有効になっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kernel.apparmor_restrict_unprivileged_userns=1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これによりOrcaがuser namespace sandboxを作れずエラーになります。&lt;/p&gt;
&lt;p&gt;制限をUbuntu 22.04相当に戻す方法もありますが、システム上の全アプリケーションに対して非特権user namespaceの制限を解除することになります。&lt;/p&gt;
&lt;p&gt;とりあえずは Orca 側の対応待ちという感じです。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;以上で無事起動しました。&lt;br&gt;
使い方などは気が向いたらまた別途。&lt;/p&gt;</description></item><item><title>Codex のレート制限リセット権の有効期限の確認方法</title><link>https://blog.ponkotools.com/posts/2026/07/09/codex/</link><pubDate>Thu, 09 Jul 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/07/09/codex/</guid><description>&lt;p&gt;Codex で付与されたレート制限リセット権は有効期限が30日間となっていますが、現状、有効期限がいつまでかを簡単に確認する術がないようです。&lt;br&gt;
以下に Windows 環境で確認するためのスクリプトが記載されていたので、これを参考に Ubuntu 用のスクリプトを作成しました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://note.com/moz_ai_tech/n/n84feff773b79" target="_blank" rel="noopener"
 &gt;https://note.com/moz_ai_tech/n/n84feff773b79&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="スクリプトの作成"&gt;&lt;a href="#%e3%82%b9%e3%82%af%e3%83%aa%e3%83%97%e3%83%88%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;スクリプトの作成
&lt;/h2&gt;&lt;p&gt;ファイル名は何でもよいですが、例えば &lt;code&gt;check_codex_reset_credits.sh&lt;/code&gt; として、以下の内容を保存してください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -euo pipefail
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;AUTH_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/.codex/auth.json&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;API_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;https://chatgpt.com/backend-api/wham/rate-limit-reset-credits&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; ! &lt;span class="nb"&gt;command&lt;/span&gt; -v jq &amp;gt;/dev/null 2&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ERROR: jq が見つかりません。先にインストールしてください。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; sudo apt update &amp;amp;&amp;amp; sudo apt install -y jq&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; ! &lt;span class="nb"&gt;command&lt;/span&gt; -v curl &amp;gt;/dev/null 2&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ERROR: curl が見つかりません。先にインストールしてください。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; sudo apt update &amp;amp;&amp;amp; sudo apt install -y curl&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; ! -f &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$AUTH_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ERROR: 認証ファイルが見つかりません: &lt;/span&gt;&lt;span class="nv"&gt;$AUTH_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Codex にログイン済みか確認してください。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ACCESS_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;jq -r &lt;span class="s1"&gt;&amp;#39;.tokens.access_token // empty&amp;#39;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$AUTH_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ACCOUNT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;jq -r &lt;span class="s1"&gt;&amp;#39;.tokens.account_id // empty&amp;#39;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$AUTH_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$ACCESS_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ERROR: access_token が取得できませんでした。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$AUTH_FILE&lt;/span&gt;&lt;span class="s2"&gt; の形式が想定と異なるか、Codex の認証状態が無効です。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;TMP_RESPONSE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;mktemp&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rm -f &amp;#34;$TMP_RESPONSE&amp;#34;&amp;#39;&lt;/span&gt; EXIT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$ACCOUNT_ID&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;HTTP_CODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; curl -sS &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -o &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$TMP_RESPONSE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -w &lt;span class="s2"&gt;&amp;#34;%{http_code}&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ACCESS_TOKEN&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;OpenAI-Beta: codex-1&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;originator: Codex Desktop&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;ChatGPT-Account-ID: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ACCOUNT_ID&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --max-time &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$API_URL&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;HTTP_CODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; curl -sS &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -o &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$TMP_RESPONSE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -w &lt;span class="s2"&gt;&amp;#34;%{http_code}&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ACCESS_TOKEN&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;OpenAI-Beta: codex-1&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;originator: Codex Desktop&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --max-time &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$API_URL&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$HTTP_CODE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; !&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;200&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ERROR: API 呼び出しに失敗しました。HTTP status: &lt;/span&gt;&lt;span class="nv"&gt;$HTTP_CODE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;レスポンス:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cat &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$TMP_RESPONSE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;jq -r &lt;span class="s1"&gt;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; def fmt_time:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; if . == null or . == &amp;#34;&amp;#34; then
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;不明&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; else
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; # jq の fromdateiso8601 は小数秒つき ISO8601 で失敗することがあるため除去する
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; sub(&amp;#34;\\.[0-9]+Z$&amp;#34;; &amp;#34;Z&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; | fromdateiso8601
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; | localtime
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; | strftime(&amp;#34;%Y-%m-%d %H:%M:%S %Z&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; end;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;利用可能なリセット権: \(.available_count // 0) 個&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;状態\t付与日時\t有効期限&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; (.credits // [])
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; | map([
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; (.status // &amp;#34;不明&amp;#34;),
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; (.granted_at | fmt_time),
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; (.expires_at | fmt_time)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; ])
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; | .[]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; | @tsv
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$TMP_RESPONSE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; column -t -s &lt;span class="s1"&gt;$&amp;#39;\t&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="実行手順"&gt;&lt;a href="#%e5%ae%9f%e8%a1%8c%e6%89%8b%e9%a0%86" class="header-anchor"&gt;&lt;/a&gt;実行手順
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install -y curl jq
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x check_codex_reset_credits.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./check_codex_reset_credits.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="注意"&gt;&lt;a href="#%e6%b3%a8%e6%84%8f" class="header-anchor"&gt;&lt;/a&gt;注意
&lt;/h2&gt;&lt;p&gt;このスクリプトは、参照記事の PowerShell 版と同じく、&lt;code&gt;~/.codex/auth.json&lt;/code&gt; から &lt;code&gt;access_token&lt;/code&gt; と &lt;code&gt;account_id&lt;/code&gt; を読み取り、&lt;code&gt;https://chatgpt.com/backend-api/wham/rate-limit-reset-credits&lt;/code&gt; に GET します。&lt;/p&gt;
&lt;p&gt;注意点として、この方法は公式に公開された安定 API ではなく、参照記事でも「内部APIを使った非公式な確認方法」と説明されています。&lt;br&gt;
Codex 側の仕様変更で動かなくなる可能性があります。&lt;/p&gt;</description></item><item><title>Ollama で Gemma4 12B を動かして VS Code から使う</title><link>https://blog.ponkotools.com/posts/2026/06/12/ollama-gemma/</link><pubDate>Fri, 12 Jun 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/06/12/ollama-gemma/</guid><description>&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 22.04&lt;/li&gt;
&lt;li&gt;CPU: Intel Core i7-11700&lt;/li&gt;
&lt;li&gt;GPU: RTX 4070 12GB&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ollama-のインストール"&gt;&lt;a href="#ollama-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;Ollama のインストール
&lt;/h2&gt;&lt;p&gt;以下のページにコマンドが記載されているので、実行します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://ollama.com/download/linux" target="_blank" rel="noopener"
 &gt;https://ollama.com/download/linux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -fsSL https://ollama.com/install.sh &lt;span class="p"&gt;|&lt;/span&gt; sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;確認&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ollama --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ollama version is 0.30.7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="gemma4-12b-のインストールと起動"&gt;&lt;a href="#gemma4-12b-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%a8%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;Gemma4 12B のインストールと起動
&lt;/h2&gt;&lt;p&gt;以下のコマンドを実行するとモデルのダウンロードが始まり、完了後に起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ollama run gemma4:12b
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; が表示されて入力受付待ちになるので、何かメッセージを入力すると応答が返ってきます。&lt;br&gt;
日本語でもいけました。&lt;br&gt;
終了するには &lt;code&gt;Ctrl + d&lt;/code&gt; を入力します。&lt;/p&gt;
&lt;p&gt;尚、ダウンロードだけしたい場合は &lt;code&gt;pull&lt;/code&gt; を使います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ollama pull gemma4:12b
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="vs-code-から使う"&gt;&lt;a href="#vs-code-%e3%81%8b%e3%82%89%e4%bd%bf%e3%81%86" class="header-anchor"&gt;&lt;/a&gt;VS Code から使う
&lt;/h2&gt;&lt;h3 id="状態確認"&gt;&lt;a href="#%e7%8a%b6%e6%85%8b%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;状態確認
&lt;/h3&gt;&lt;p&gt;Ollama はインストールすれば勝手にサービスとして登録されます。&lt;br&gt;
以下のコマンドで &lt;code&gt;Ollama is running&lt;/code&gt; と返ってくれば OK です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://localhost:11434
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Ollama is running
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;ollama run&lt;/code&gt; を実行しておく必要もありません。&lt;/p&gt;
&lt;h3 id="github-copilot-chat-から使う"&gt;&lt;a href="#github-copilot-chat-%e3%81%8b%e3%82%89%e4%bd%bf%e3%81%86" class="header-anchor"&gt;&lt;/a&gt;GitHub Copilot Chat から使う
&lt;/h3&gt;&lt;blockquote class="alert alert-note"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;📝&lt;/span&gt;
 &lt;span class="alert-title"&gt;注記&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;先に結論として、GitHub Copilot Chat からは上手くいかなかったので、後述の Continue を使いました&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;p&gt;以下に説明がありますが、&lt;code&gt;ollama launch vscode&lt;/code&gt; を実行します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.ollama.com/integrations/vscode" target="_blank" rel="noopener"
 &gt;https://docs.ollama.com/integrations/vscode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ollama が VS Code を検出し、ローカルモデルとの連携設定を支援してくれます。&lt;br&gt;
実行後、以下のような設定画面が表示されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;ollama&lt;/span&gt; &lt;span class="n"&gt;launch&lt;/span&gt; &lt;span class="n"&gt;vscode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Select&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Visual&lt;/span&gt; &lt;span class="n"&gt;Studio&lt;/span&gt; &lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Recommended&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;minimax&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cloud&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;art&lt;/span&gt; &lt;span class="n"&gt;coding&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;capabilities&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;multimodal&lt;/span&gt; &lt;span class="n"&gt;reasoning&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;support&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;kimi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;k2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cloud&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;art&lt;/span&gt; &lt;span class="n"&gt;coding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;long&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;horizon&lt;/span&gt; &lt;span class="n"&gt;execution&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;multimodal&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;swarm&lt;/span&gt; &lt;span class="n"&gt;capability&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;glm&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;5.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cloud&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;horizon&lt;/span&gt; &lt;span class="n"&gt;agentic&lt;/span&gt; &lt;span class="n"&gt;engineering&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;autonomous&lt;/span&gt; &lt;span class="n"&gt;execution&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;sustained&lt;/span&gt; &lt;span class="n"&gt;iteration&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;qwen3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cloud&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Reasoning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;agentic&lt;/span&gt; &lt;span class="k"&gt;tool&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;vision&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;nemotron&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;super&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cloud&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Reasoning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;agentic&lt;/span&gt; &lt;span class="k"&gt;tool&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gemma4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cloud&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Agentic&lt;/span&gt; &lt;span class="n"&gt;workflows&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;multimodal&lt;/span&gt; &lt;span class="n"&gt;reasoning&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gemma4&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Agentic&lt;/span&gt; &lt;span class="n"&gt;workflows&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;multimodal&lt;/span&gt; &lt;span class="n"&gt;reasoning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;downloaded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;qwen3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Agentic&lt;/span&gt; &lt;span class="n"&gt;software&lt;/span&gt; &lt;span class="n"&gt;engineering&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;multimodal&lt;/span&gt; &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;downloaded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;More&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;▸&lt;/span&gt; &lt;span class="n"&gt;gemma4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="n"&gt;selected&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;press&lt;/span&gt; &lt;span class="n"&gt;tab&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;edit&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;すでにダウンロード済みの &lt;code&gt;gemma4:12b&lt;/code&gt; を選択します。&lt;/p&gt;
&lt;p&gt;VS Code を再起動すると、GitHub Copilot Chat のモデル選択で &lt;code&gt;gemma:12b&lt;/code&gt; が選択できるようになっています。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="337px" data-flex-grow="140" height="304" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/06/12/ollama-gemma/00.webp" width="428"&gt;&lt;/p&gt;
&lt;h4 id="レスポンスでエラー"&gt;&lt;a href="#%e3%83%ac%e3%82%b9%e3%83%9d%e3%83%b3%e3%82%b9%e3%81%a7%e3%82%a8%e3%83%a9%e3%83%bc" class="header-anchor"&gt;&lt;/a&gt;レスポンスでエラー
&lt;/h4&gt;&lt;p&gt;試しに GitHub Copilot Chat から gemma4:12b にメッセージを送ると以下のエラーが返ってきました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sorry, your request failed. Please try again.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client Request Id: 11cba335-5cfd-41d2-93ac-26d191e904f8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Reason: Response too long.: Error: Response too long. at _G._provideLanguageModelResponse (/usr/share/code/resources/app/extensions/copilot/dist/extension.js:1710:13790) at process.processTicksAndRejections (node:internal/process/task_queues:104:5) at async _G.provideLanguageModelResponse (/usr/share/code/resources/app/extensions/copilot/dist/extension.js:1710:14793)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;GitHub Copilot Chat の Local Models 機能はまだ比較的新しく、上手くいかない等の報告も多数あるようです。&lt;/p&gt;
&lt;p&gt;なので、GitHub Copilot Chat から使うのは諦めて、後述の continue を使いました。&lt;/p&gt;
&lt;h3 id="continue-から使う"&gt;&lt;a href="#continue-%e3%81%8b%e3%82%89%e4%bd%bf%e3%81%86" class="header-anchor"&gt;&lt;/a&gt;Continue から使う
&lt;/h3&gt;&lt;p&gt;VS Code の拡張機能から Continue をインストールします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="993px" data-flex-grow="413" height="158" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/06/12/ollama-gemma/01.webp" width="654"&gt;&lt;/p&gt;
&lt;p&gt;インストールしたらサイドバーにアイコンが追加されるので、クリックします。&lt;br&gt;
&lt;code&gt;Select model&lt;/code&gt; から &lt;code&gt;Add Chat model&lt;/code&gt; を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="294px" data-flex-grow="122" height="485" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/06/12/ollama-gemma/02.webp" width="595"&gt;&lt;/p&gt;
&lt;p&gt;以下のように選択肢、Connect を押します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provider: Ollama&lt;/li&gt;
&lt;li&gt;Model: Autodetect&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="211px" data-flex-grow="88" height="533" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/06/12/ollama-gemma/03.webp" width="470"&gt;&lt;/p&gt;
&lt;p&gt;すると、モデルで &lt;code&gt;gemma4:12b&lt;/code&gt; が選択できるようになっています。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="464px" data-flex-grow="193" height="285" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/06/12/ollama-gemma/04.webp" width="552"&gt;&lt;/p&gt;
&lt;p&gt;これで使えるようになります。&lt;/p&gt;
&lt;h2 id="モデルのロードアンロードについて"&gt;&lt;a href="#%e3%83%a2%e3%83%87%e3%83%ab%e3%81%ae%e3%83%ad%e3%83%bc%e3%83%89%e3%82%a2%e3%83%b3%e3%83%ad%e3%83%bc%e3%83%89%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6" class="header-anchor"&gt;&lt;/a&gt;モデルのロード・アンロードについて
&lt;/h2&gt;&lt;p&gt;Ollama は、リクエストが来るとモデルをメモリにロードし、一定時間使われなければ自動でアンロードするそうです。&lt;br&gt;
公式FAQでは、デフォルトではモデルはメモリ上に5分保持され、その後アンロードされると説明されています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.ollama.com/faq?utm_source=chatgpt.com" target="_blank" rel="noopener"
 &gt;https://docs.ollama.com/faq?utm_source=chatgpt.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>VS Code で WSL 上の SSH の設定を使って Remote SSH で接続する</title><link>https://blog.ponkotools.com/posts/2026/06/03/vscode-remote-ssh/</link><pubDate>Wed, 03 Jun 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/06/03/vscode-remote-ssh/</guid><description>&lt;p&gt;以下に Windows の bat ファイルを使って WSL の SSH クライアントを呼び出す方法が書いてあったので、やり方をまとめてみました。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/microsoft/vscode-remote-release/issues/937#issuecomment-578416517" target="_blank" rel="noopener"
 &gt;https://github.com/microsoft/vscode-remote-release/issues/937#issuecomment-578416517&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;尚、上記のやり方だと Windows 側の設定が使えなくなります。
私はそれで問題ありませんが、併用したいという場合の解決策は以下で提示されていました。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://zenn.dev/kurusugawa/articles/vscode-remote-ssh-with-wsl" target="_blank" rel="noopener"
 &gt;https://zenn.dev/kurusugawa/articles/vscode-remote-ssh-with-wsl&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="概要"&gt;&lt;a href="#%e6%a6%82%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;概要
&lt;/h2&gt;&lt;p&gt;VS Codeの「Remote - SSH」拡張機能はデフォルトでWindows側のOpenSSH（またはGit for WindowsのSSH）を使用するため、WSL（Linux）側に設定した &lt;code&gt;~/.ssh/config&lt;/code&gt; や鍵、ControlMasterなどの機能を利用することができません。&lt;/p&gt;
&lt;p&gt;解決策は、「Windows側でダミーのバッチファイル（&lt;code&gt;.bat&lt;/code&gt;）を作成し、その中からWSLの &lt;code&gt;ssh&lt;/code&gt; コマンドを呼び出すようにVS Codeに設定する」という方法です。&lt;/p&gt;
&lt;h2 id="設定手順"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a%e6%89%8b%e9%a0%86" class="header-anchor"&gt;&lt;/a&gt;設定手順
&lt;/h2&gt;&lt;h3 id="1-バッチファイルsshbatの作成"&gt;&lt;a href="#1-%e3%83%90%e3%83%83%e3%83%81%e3%83%95%e3%82%a1%e3%82%a4%e3%83%absshbat%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;1. バッチファイル（&lt;code&gt;ssh.bat&lt;/code&gt;）の作成
&lt;/h3&gt;&lt;p&gt;Windows　側の適当なフォルダ（例: &lt;code&gt;C:\Users\ユーザー名\ssh.bat&lt;/code&gt; など）に &lt;code&gt;ssh.bat&lt;/code&gt; という名前のファイルを作成し、以下の内容を記述します。&lt;/p&gt;
&lt;p&gt;※バッチファイルを作成する際は、文字コード（エンコーディング）を &lt;strong&gt;「ANSI」または「UTF-8」&lt;/strong&gt; で保存してください。（UTF-16だと正しく動作しない場合があります）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;@echo off
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;C:&lt;span class="se"&gt;\W&lt;/span&gt;indows&lt;span class="se"&gt;\S&lt;/span&gt;ystem32&lt;span class="se"&gt;\w&lt;/span&gt;sl.exe bash -ic &lt;span class="s2"&gt;&amp;#34;ssh %*&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-vs-codewindows側の-settingsjson-の編集"&gt;&lt;a href="#2-vs-codewindows%e5%81%b4%e3%81%ae-settingsjson-%e3%81%ae%e7%b7%a8%e9%9b%86" class="header-anchor"&gt;&lt;/a&gt;2. VS Code（Windows側）の &lt;code&gt;settings.json&lt;/code&gt; の編集
&lt;/h3&gt;&lt;p&gt;次に、VS Codeが標準の SSH ではなく、今作成したバッチファイルを使用するように設定します。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Windows側でVS Codeを開きます。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl + ,&lt;/code&gt; で設定を開き、画面右上の「設定(JSON)を開く」アイコンをクリックして settings.json を開きます。&lt;/li&gt;
&lt;li&gt;以下の2つの設定項目を追加（または既存のものを修正）します。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 1で作成したバッチファイルの「絶対パス」を指定（バックスラッシュは2つ重ねる）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;remote.SSH.path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;C:\\Users\\あなたのユーザー名\\bin\\ssh.bat&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// ローカル（Windows）側での不要なサーバープロセスの立ち上げを抑制する
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;remote.SSH.useLocalServer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-リモート接続を実行する"&gt;&lt;a href="#3-%e3%83%aa%e3%83%a2%e3%83%bc%e3%83%88%e6%8e%a5%e7%b6%9a%e3%82%92%e5%ae%9f%e8%a1%8c%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;3. リモート接続を実行する
&lt;/h3&gt;&lt;p&gt;設定が完了したら、実際に接続を行います。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;設定を確実に反映させるため、VS Codeを一度完全に閉じて再起動します。&lt;/li&gt;
&lt;li&gt;左下の緑色のリモート接続アイコン（または F1 キーを押して Remote-SSH: Connect to Host&amp;hellip;）をクリックします。&lt;/li&gt;
&lt;li&gt;WSL（Linux）側の ~/.ssh/config に記載されているホスト名（例: oci-ubuntu）を選択します。&lt;/li&gt;
&lt;li&gt;初回接続時のみ「接続先のOSプラットフォーム（Linux / Windows / macOS）」を聞かれるので、Linux を選択します。&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>OCI や AWS EC2 でセッション切断後も処理を止めないよう tmux を使う</title><link>https://blog.ponkotools.com/posts/2026/05/30/tmux/</link><pubDate>Sat, 30 May 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/05/30/tmux/</guid><description>&lt;p&gt;OCI や AWS EC2 で作業していると、SSH セッションを閉じたタイミングで実行中のプログラムが止まってしまうことがあります。&lt;/p&gt;
&lt;p&gt;この問題は、tmux の「セッションを切り離す（detach）」を使うだけでほぼ解決できます。&lt;br&gt;
私は今回初めて tmux を使ったため、必要な操作に限定してメモしておきます。&lt;/p&gt;
&lt;h2 id="先にまとめ"&gt;&lt;a href="#%e5%85%88%e3%81%ab%e3%81%be%e3%81%a8%e3%82%81" class="header-anchor"&gt;&lt;/a&gt;先にまとめ
&lt;/h2&gt;&lt;p&gt;「SSH を閉じても処理を動かし続ける」目的なら、tmux は以下だけで運用できます。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SSH ログイン後に tmux セッションを作る&lt;/li&gt;
&lt;li&gt;tmux 内でプログラムを起動する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+b&lt;/code&gt; → &lt;code&gt;d&lt;/code&gt; で切り離す&lt;/li&gt;
&lt;li&gt;SSH を切断しても処理は継続する&lt;/li&gt;
&lt;li&gt;再ログイン後に tmux へ再接続する&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;コマンドだけ見ると以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# セッション作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tmux new -s app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# （tmux 内で）プログラム実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python main.py
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 切り離し: Ctrl+b, d&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# いまあるセッション確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tmux ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 再接続&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tmux attach -t app
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="tmux-のインストール"&gt;&lt;a href="#tmux-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;tmux のインストール
&lt;/h2&gt;&lt;p&gt;Ubuntu 系なら以下で入ります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install -y tmux
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;確認（バージョン表示）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tmux -V
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="まずは-1-回動かしてみる"&gt;&lt;a href="#%e3%81%be%e3%81%9a%e3%81%af-1-%e5%9b%9e%e5%8b%95%e3%81%8b%e3%81%97%e3%81%a6%e3%81%bf%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;まずは 1 回動かしてみる
&lt;/h2&gt;&lt;h3 id="1-セッションを作る"&gt;&lt;a href="#1-%e3%82%bb%e3%83%83%e3%82%b7%e3%83%a7%e3%83%b3%e3%82%92%e4%bd%9c%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;1. セッションを作る
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tmux new -s app
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;app&lt;/code&gt; はセッション名です。&lt;br&gt;
あとで再接続するときに使うので、用途が分かる名前を付けると楽です。&lt;/p&gt;
&lt;blockquote class="alert alert-note"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;📝&lt;/span&gt;
 &lt;span class="alert-title"&gt;注記&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;tmux だけ打った場合、もし tmux サーバーがまだ動いていなければ、新しいセッションを作って接続します（デフォルト名で作成）。&lt;br&gt;
すでに tmux が動いていて接続済みでない場合は、最近使われたセッションにアタッチします（新しいセッションは作成されません）。
上記のコマンドは明示的に新規の名前付きセッションを作るコマンドになります。&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;h3 id="2-プログラムを起動する"&gt;&lt;a href="#2-%e3%83%97%e3%83%ad%e3%82%b0%e3%83%a9%e3%83%a0%e3%82%92%e8%b5%b7%e5%8b%95%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;2. プログラムを起動する
&lt;/h3&gt;&lt;p&gt;tmux の画面の中で、普段どおりコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python main.py
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;たとえば API サーバーなら、以下のように常駐するコマンドでも同じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uvicorn app:app --host 0.0.0.0 --port &lt;span class="m"&gt;8000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-セッションを切り離すdetach"&gt;&lt;a href="#3-%e3%82%bb%e3%83%83%e3%82%b7%e3%83%a7%e3%83%b3%e3%82%92%e5%88%87%e3%82%8a%e9%9b%a2%e3%81%99detach" class="header-anchor"&gt;&lt;/a&gt;3. セッションを切り離す（detach）
&lt;/h3&gt;&lt;p&gt;以下の順でキーを押します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Ctrl+b&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;d&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これで tmux の外に戻ります。&lt;br&gt;
プログラムは tmux セッション内でそのまま動き続けますので、SSH 自体を切断して問題ありません。&lt;br&gt;
再ログイン後に tmux へ戻れます。&lt;/p&gt;
&lt;h3 id="4-再接続するattach"&gt;&lt;a href="#4-%e5%86%8d%e6%8e%a5%e7%b6%9a%e3%81%99%e3%82%8battach" class="header-anchor"&gt;&lt;/a&gt;4. 再接続する（attach）
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;tmux ls&lt;/code&gt; でセッション一覧を見て、名前を確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tmux ls
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下のコマンドで再接続します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tmux attach -t app
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="セッションを終了して抜けるプロセスを停止してセッションを閉じる"&gt;&lt;a href="#%e3%82%bb%e3%83%83%e3%82%b7%e3%83%a7%e3%83%b3%e3%82%92%e7%b5%82%e4%ba%86%e3%81%97%e3%81%a6%e6%8a%9c%e3%81%91%e3%82%8b%e3%83%97%e3%83%ad%e3%82%bb%e3%82%b9%e3%82%92%e5%81%9c%e6%ad%a2%e3%81%97%e3%81%a6%e3%82%bb%e3%83%83%e3%82%b7%e3%83%a7%e3%83%b3%e3%82%92%e9%96%89%e3%81%98%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;セッションを終了して抜ける（プロセスを停止してセッションを閉じる）
&lt;/h2&gt;&lt;p&gt;tmux をデタッチせずにそのままセッションを終了して抜けたい場合は、主に次の方法があります。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;セッション内から終了する（推奨 — プロセスを安全に停止）&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;tmux attach -t &amp;lt;セッション名&amp;gt;&lt;/code&gt; でセッションに戻る&lt;/li&gt;
&lt;li&gt;実行中のプロセスを &lt;code&gt;Ctrl+C&lt;/code&gt; などで停止する&lt;/li&gt;
&lt;li&gt;シェルで &lt;code&gt;exit&lt;/code&gt; または &lt;code&gt;Ctrl+D&lt;/code&gt; を押すとウィンドウが閉じ、最後のウィンドウが閉じるとセッションは終了します&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;外からセッションを強制的に終了する（注意: プロセスが強制終了される）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tmux kill-session -t &amp;lt;セッション名&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;全てのセッションを終了する場合は &lt;code&gt;tmux kill-server&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;注意: セッションを閉じると、そのセッション内で動いていたプロセスは終了します。処理を継続させたい場合はデタッチしてください。&lt;/p&gt;
&lt;h2 id="今回の用途で最低限覚えるコマンド"&gt;&lt;a href="#%e4%bb%8a%e5%9b%9e%e3%81%ae%e7%94%a8%e9%80%94%e3%81%a7%e6%9c%80%e4%bd%8e%e9%99%90%e8%a6%9a%e3%81%88%e3%82%8b%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;今回の用途で最低限覚えるコマンド
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;用途&lt;/th&gt;
 &lt;th&gt;コマンド&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;新規セッション作成&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;tmux new -s app&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;セッション一覧&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;tmux ls&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;セッション再接続&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;tmux attach -t app&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;セッション削除（停止）&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;tmux kill-session -t app&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote class="alert alert-tip"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;💡&lt;/span&gt;
 &lt;span class="alert-title"&gt;ヒント&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;セッション内で動いているプロセスを止めたいときは、まず tmux に再接続して &lt;code&gt;Ctrl+c&lt;/code&gt; で停止するのが安全です。&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;h2 id="キー操作の最小セット"&gt;&lt;a href="#%e3%82%ad%e3%83%bc%e6%93%8d%e4%bd%9c%e3%81%ae%e6%9c%80%e5%b0%8f%e3%82%bb%e3%83%83%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;キー操作の最小セット
&lt;/h2&gt;&lt;p&gt;tmux は &lt;code&gt;Ctrl+b&lt;/code&gt; を押したあとに次のキーを押す操作が基本です（prefix キー）。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;コマンド&lt;/th&gt;
 &lt;th&gt;内容&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Ctrl+b&lt;/code&gt; → &lt;code&gt;d&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;セッション切り離し&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Ctrl+b&lt;/code&gt; → &lt;code&gt;c&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;新しいウィンドウ作成&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Ctrl+b&lt;/code&gt; → &lt;code&gt;n&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;次のウィンドウへ移動&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Ctrl+b&lt;/code&gt; → &lt;code&gt;p&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;前のウィンドウへ移動&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;Ctrl+b&lt;/code&gt; → &lt;code&gt;,&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;ウィンドウ名を変更&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;最初は &lt;code&gt;Ctrl+b&lt;/code&gt; → &lt;code&gt;d&lt;/code&gt; だけ覚えれば十分です。&lt;/p&gt;
&lt;h2 id="よくあるハマりどころ"&gt;&lt;a href="#%e3%82%88%e3%81%8f%e3%81%82%e3%82%8b%e3%83%8f%e3%83%9e%e3%82%8a%e3%81%a9%e3%81%93%e3%82%8d" class="header-anchor"&gt;&lt;/a&gt;よくあるハマりどころ
&lt;/h2&gt;&lt;h3 id="ssh-を切ったら止まった"&gt;&lt;a href="#ssh-%e3%82%92%e5%88%87%e3%81%a3%e3%81%9f%e3%82%89%e6%ad%a2%e3%81%be%e3%81%a3%e3%81%9f" class="header-anchor"&gt;&lt;/a&gt;SSH を切ったら止まった
&lt;/h3&gt;&lt;p&gt;tmux の中で起動せず、通常シェルで起動している可能性があります。&lt;br&gt;
&lt;code&gt;tmux attach -t app&lt;/code&gt; で戻って、そこで起動し直してください。&lt;/p&gt;
&lt;h3 id="tmux-attach-でno-sessionsになる"&gt;&lt;a href="#tmux-attach-%e3%81%a7no-sessions%e3%81%ab%e3%81%aa%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;&lt;code&gt;tmux attach&lt;/code&gt; で「no sessions」になる
&lt;/h3&gt;&lt;p&gt;セッションが存在しない状態です。新しく作成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tmux new -s app
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="セッション名を忘れる"&gt;&lt;a href="#%e3%82%bb%e3%83%83%e3%82%b7%e3%83%a7%e3%83%b3%e5%90%8d%e3%82%92%e5%bf%98%e3%82%8c%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;セッション名を忘れる
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tmux ls
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一覧を出して、その名前で attach すれば戻れます。&lt;/p&gt;</description></item><item><title>OCI の Ubuntu インスタンスの初期設定</title><link>https://blog.ponkotools.com/posts/2026/05/29/oci-ubuntu/</link><pubDate>Fri, 29 May 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/05/29/oci-ubuntu/</guid><description>&lt;h2 id="swap-の設定"&gt;&lt;a href="#swap-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;swap の設定
&lt;/h2&gt;&lt;p&gt;以下のように、Ubuntu のイメージにはスワップがありません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ free -m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; total used free shared buff/cache available
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Mem: &lt;span class="m"&gt;954&lt;/span&gt; &lt;span class="m"&gt;343&lt;/span&gt; &lt;span class="m"&gt;225&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="m"&gt;538&lt;/span&gt; &lt;span class="m"&gt;610&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Swap: &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;2GB のスワップファイル（Swap）を追加します。&lt;br&gt;
すべてのコマンドは、管理者権限（&lt;code&gt;sudo&lt;/code&gt;）を付けてターミナルで実行します。&lt;/p&gt;
&lt;h3 id="1-スワップファイルの作成"&gt;&lt;a href="#1-%e3%82%b9%e3%83%af%e3%83%83%e3%83%97%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;1. スワップファイルの作成
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;dd&lt;/code&gt; または &lt;code&gt;fallocate&lt;/code&gt; コマンドで 2GB のファイルを作成します。ここでは確実かつ高速な &lt;code&gt;fallocate&lt;/code&gt; を使用します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo fallocate -l 2G /swapfile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote class="alert alert-warning"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;⚠️&lt;/span&gt;
 &lt;span class="alert-title"&gt;警告&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;もし「fallocate failed: Operation not supported」のようなエラーが出た場合は、以下の &lt;code&gt;dd&lt;/code&gt; コマンドを代わりに試してください。&lt;br&gt;
&lt;code&gt;sudo dd if=/dev/zero of=/swapfile bs=1M count=2048&lt;/code&gt;&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;h3 id="2-適切な権限の設定"&gt;&lt;a href="#2-%e9%81%a9%e5%88%87%e3%81%aa%e6%a8%a9%e9%99%90%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;2. 適切な権限の設定
&lt;/h3&gt;&lt;p&gt;セキュリティのため、スワップファイルは root ユーザーのみが読み書きできるように権限を &lt;code&gt;600&lt;/code&gt; に制限します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo chmod &lt;span class="m"&gt;600&lt;/span&gt; /swapfile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-スワップ領域の初期化"&gt;&lt;a href="#3-%e3%82%b9%e3%83%af%e3%83%83%e3%83%97%e9%a0%98%e5%9f%9f%e3%81%ae%e5%88%9d%e6%9c%9f%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;3. スワップ領域の初期化
&lt;/h3&gt;&lt;p&gt;作成したファイルをスワップ領域としてフォーマットします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo mkswap /swapfile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-スワップの有効化"&gt;&lt;a href="#4-%e3%82%b9%e3%83%af%e3%83%83%e3%83%97%e3%81%ae%e6%9c%89%e5%8a%b9%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;4. スワップの有効化
&lt;/h3&gt;&lt;p&gt;システムにスワップファイルを認識させ、有効化します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo swapon /swapfile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="5-設定の確認"&gt;&lt;a href="#5-%e8%a8%ad%e5%ae%9a%e3%81%ae%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;5. 設定の確認
&lt;/h3&gt;&lt;p&gt;スワップが正しく有効化されたか確認します。2GB（約 2.0GiB）のスワップが表示されていれば成功です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo swapon --show
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# または&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;free -h
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="6-再起動後も自動で有効化する設定"&gt;&lt;a href="#6-%e5%86%8d%e8%b5%b7%e5%8b%95%e5%be%8c%e3%82%82%e8%87%aa%e5%8b%95%e3%81%a7%e6%9c%89%e5%8a%b9%e5%8c%96%e3%81%99%e3%82%8b%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;6. 再起動後も自動で有効化する設定
&lt;/h3&gt;&lt;p&gt;上記の設定だけでは、インスタンスを再起動するとスワップが解除されてしまいます。再起動後も自動的に有効化されるよう、&lt;code&gt;/etc/fstab&lt;/code&gt; に追記します。&lt;/p&gt;
&lt;h4 id="6-1-fstab-のバックアップ推奨"&gt;&lt;a href="#6-1-fstab-%e3%81%ae%e3%83%90%e3%83%83%e3%82%af%e3%82%a2%e3%83%83%e3%83%97%e6%8e%a8%e5%a5%a8" class="header-anchor"&gt;&lt;/a&gt;6-1. fstab のバックアップ（推奨）
&lt;/h4&gt;&lt;p&gt;念のため、設定ファイルをバックアップしておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo cp /etc/fstab /etc/fstab.bak
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="6-2-設定の追記"&gt;&lt;a href="#6-2-%e8%a8%ad%e5%ae%9a%e3%81%ae%e8%bf%bd%e8%a8%98" class="header-anchor"&gt;&lt;/a&gt;6-2. 設定の追記
&lt;/h4&gt;&lt;p&gt;以下のコマンドを実行して、&lt;code&gt;/etc/fstab&lt;/code&gt; の末尾に設定を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/swapfile none swap sw 0 0&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee -a /etc/fstab
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h3 id="おまけカーネルパラメータの最適化推奨"&gt;&lt;a href="#%e3%81%8a%e3%81%be%e3%81%91%e3%82%ab%e3%83%bc%e3%83%8d%e3%83%ab%e3%83%91%e3%83%a9%e3%83%a1%e3%83%bc%e3%82%bf%e3%81%ae%e6%9c%80%e9%81%a9%e5%8c%96%e6%8e%a8%e5%a5%a8" class="header-anchor"&gt;&lt;/a&gt;【おまけ】カーネルパラメータの最適化（推奨）
&lt;/h3&gt;&lt;p&gt;Linux には、メモリがどれくらい減ったらスワップを開始するかを決める &lt;code&gt;swappiness&lt;/code&gt; という値があります。&lt;br&gt;
初期値は &lt;code&gt;60&lt;/code&gt; であることが多いですが、クラウド環境（特に SSD ストレージ）では **&lt;code&gt;10&lt;/code&gt;〜&lt;code&gt;20**&lt;/code&gt; 程度に下げて、できるだけ物理メモリを優先して使うように設定するのが一般的です。&lt;/p&gt;
&lt;h4 id="1-現在の-swappiness-を確認"&gt;&lt;a href="#1-%e7%8f%be%e5%9c%a8%e3%81%ae-swappiness-%e3%82%92%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;1. 現在の swappiness を確認
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat /proc/sys/vm/swappiness
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="2-一時的に-10-に変更"&gt;&lt;a href="#2-%e4%b8%80%e6%99%82%e7%9a%84%e3%81%ab-10-%e3%81%ab%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;2. 一時的に &lt;code&gt;10&lt;/code&gt; に変更
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo sysctl vm.swappiness&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="3-永続的に反映"&gt;&lt;a href="#3-%e6%b0%b8%e7%b6%9a%e7%9a%84%e3%81%ab%e5%8f%8d%e6%98%a0" class="header-anchor"&gt;&lt;/a&gt;3. 永続的に反映
&lt;/h4&gt;&lt;p&gt;再起動後もこの設定を維持するため、&lt;code&gt;/etc/sysctl.conf&lt;/code&gt; の末尾に追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;vm.swappiness=10&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee -a /etc/sysctl.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;p&gt;これで 2GB のスワップ設定はすべて完了です！&lt;/p&gt;
&lt;h2 id="タイムゾーンの変更"&gt;&lt;a href="#%e3%82%bf%e3%82%a4%e3%83%a0%e3%82%be%e3%83%bc%e3%83%b3%e3%81%ae%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;タイムゾーンの変更
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 現在のタイムゾーンを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;timedatectl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# JST に変更&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo timedatectl set-timezone Asia/Tokyo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 変更されたことを確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;timedatectl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="nano-のインストール"&gt;&lt;a href="#nano-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;nano のインストール
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install -y nano
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="git-のインストール"&gt;&lt;a href="#git-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;git のインストール
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install -y git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="glab-のインストールと認証"&gt;&lt;a href="#glab-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%a8%e8%aa%8d%e8%a8%bc" class="header-anchor"&gt;&lt;/a&gt;glab のインストールと認証
&lt;/h2&gt;&lt;p&gt;諸事情で GitHub ではなく GitLab を使っているので、glab をインストールします。&lt;/p&gt;
&lt;h3 id="1-ダウンロード"&gt;&lt;a href="#1-%e3%83%80%e3%82%a6%e3%83%b3%e3%83%ad%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;1. ダウンロード
&lt;/h3&gt;&lt;p&gt;apt でインストールできるバージョンは古いので、公式リリースからダウンロードしてインストールします。&lt;/p&gt;
&lt;p&gt;詳細は以下を参照してください。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://blog.ponkotools.com/posts/2026/05/10/glab/" target="_blank" rel="noopener"
 &gt;https://blog.ponkotools.com/posts/2026/05/10/glab/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="2-gitlab-でのアクセストークンpatの発行"&gt;&lt;a href="#2-gitlab-%e3%81%a7%e3%81%ae%e3%82%a2%e3%82%af%e3%82%bb%e3%82%b9%e3%83%88%e3%83%bc%e3%82%af%e3%83%b3pat%e3%81%ae%e7%99%ba%e8%a1%8c" class="header-anchor"&gt;&lt;/a&gt;2. GitLab でのアクセストークン（PAT）の発行
&lt;/h3&gt;&lt;p&gt;CLI から GitLab にアクセスするために、事前にブラウザ側（GitLab のウェブ画面）で Personal Access Token（個人用アクセストークン） を発行しておく必要があります。&lt;br&gt;
WSL を使っているからか、web での認証ではうまくいきませんでした。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;GitLab にログインします（SaaS 版の gitlab.com または社内などのオンプレミス版）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;面左上の自分のアイコン ＞ Preferences（設定） ＞ 左メニューの Access Tokens の順に開きます。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add new token をクリックし、以下のように入力します：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Token name: 任意の名前（例: oci-ubuntu-cli）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Expiration date: 空欄（無期限）または任意の有効期限&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Scopes（権限）: CLI をフル活用するために、&lt;code&gt;api&lt;/code&gt; と &lt;code&gt;write_repository&lt;/code&gt;以下にチェックを入れます。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Create personal access token をクリックします。&lt;/p&gt;
&lt;p&gt;画面に一度だけトークン（glpat-xxxx&amp;hellip;）が表示されるので、必ずコピーして手元に控えておきます。（画面を閉じると二度と見られなくなります）&lt;/p&gt;
&lt;h3 id="3-cli-の認証設定ログイン"&gt;&lt;a href="#3-cli-%e3%81%ae%e8%aa%8d%e8%a8%bc%e8%a8%ad%e5%ae%9a%e3%83%ad%e3%82%b0%e3%82%a4%e3%83%b3" class="header-anchor"&gt;&lt;/a&gt;3. CLI の認証設定（ログイン）
&lt;/h3&gt;&lt;p&gt;OCI の Ubuntu ターミナルに戻り、以下のコマンドを実行して対話型セットアップを開始します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;glab auth login
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実行すると、いくつか質問されるので以下のように回答していきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┃ What GitLab instance &lt;span class="k"&gt;do&lt;/span&gt; you want to sign in to?
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┃ &amp;gt; gitlab.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┃ GitLab Self-Managed or GitLab Dedicated instance
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;gitLab.com（本家）を使っている場合は、そのまま gitLab.com を選択して Enter。&lt;br&gt;
自社サーバーなどの場合は GitLab Self-Managed or GitLab Dedicated instance を選択し、その後 URL（例: &lt;a class="link" href="https://gitlab.example.com" target="_blank" rel="noopener"
 &gt;https://gitlab.example.com&lt;/a&gt;）を入力します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Signing into gitlab.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┃ How would you like to sign in?
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┃ &amp;gt; Token
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┃ Web
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Token を選択します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Signing into gitlab.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┃ What domains does this host use &lt;span class="k"&gt;for&lt;/span&gt; the container registry and image dependency proxy?
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┃ &amp;gt; gitlab.com,gitlab.com:443,registry.gitlab.com 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そのまま Enter を押します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The minimum required scopes are &lt;span class="s1"&gt;&amp;#39;api&amp;#39;&lt;/span&gt; and &lt;span class="s1"&gt;&amp;#39;write_repository&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Generate a personal access token at https://gitlab.com/-/user_settings/personal_access_tokens?scopes&lt;span class="o"&gt;=&lt;/span&gt;api,write_repository
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┃ Paste your authentication token:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┃ &amp;gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;先ほど GitLab 画面でコピーしたトークン（glpat-xxxx&amp;hellip;）を貼り付けて Enter を押します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┃ Choose default Git protocol:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┃ SSH
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┃ &amp;gt; HTTPS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┃ HTTP
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;HTTPS を選択します。&lt;/p&gt;
&lt;p&gt;セットアップが完了したら、以下のコマンドで無事にログインできているか確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;glab auth status
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ご自身のユーザー名や「Logged in to gitlab.com」といったステータスが表示されれば、GitLab CLI の設定はすべて完了です！&lt;/p&gt;
&lt;h2 id="tmux-のインストール"&gt;&lt;a href="#tmux-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;tmux のインストール
&lt;/h2&gt;&lt;p&gt;セッションが切れても実行中のプログラムが停止しないよう tmux を使うためにインストールします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install -y tmux
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="docker-のインストール"&gt;&lt;a href="#docker-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;docker のインストール
&lt;/h2&gt;&lt;h3 id="1-インストール"&gt;&lt;a href="#1-%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;1. インストール
&lt;/h3&gt;&lt;p&gt;公式ドキュメントの Install using the apt repository に従って最新版の docker をインストールします。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="2-docker-の権限を設定-sudo-を不要にする"&gt;&lt;a href="#2-docker-%e3%81%ae%e6%a8%a9%e9%99%90%e3%82%92%e8%a8%ad%e5%ae%9a-sudo-%e3%82%92%e4%b8%8d%e8%a6%81%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;2. docker の権限を設定 (sudo を不要にする)
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo gpasswd -a &lt;span class="k"&gt;$(&lt;/span&gt;whoami&lt;span class="k"&gt;)&lt;/span&gt; docker
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo chgrp docker /var/run/docker.sock
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="不要なサービスの停止"&gt;&lt;a href="#%e4%b8%8d%e8%a6%81%e3%81%aa%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%81%ae%e5%81%9c%e6%ad%a2" class="header-anchor"&gt;&lt;/a&gt;不要なサービスの停止
&lt;/h2&gt;&lt;p&gt;参考: &lt;a class="link" href="https://qiita.com/ynott/items/4312cb34611d2e462779" target="_blank" rel="noopener"
 &gt;https://qiita.com/ynott/items/4312cb34611d2e462779&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;systemctl | grep running&lt;/code&gt; で稼働中のサービス一覧を出力し、そのうち不要なものを AI に尋ねた結果が以下です。&lt;/p&gt;
&lt;h3 id="確実に停止無効化して良いサービス"&gt;&lt;a href="#%e7%a2%ba%e5%ae%9f%e3%81%ab%e5%81%9c%e6%ad%a2%e7%84%a1%e5%8a%b9%e5%8c%96%e3%81%97%e3%81%a6%e8%89%af%e3%81%84%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9" class="header-anchor"&gt;&lt;/a&gt;確実に停止・無効化して良いサービス
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;サービス名&lt;/th&gt;
 &lt;th&gt;役割と停止して良い理由&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ModemManager.service&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;3G/4G/5G などのモバイルモデムを管理するサービス。クラウドのサーバーでモデムを使うことはないため、完全に不要です。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;fwupd.service&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;マザーボードやデバイスのファームウェアをアップデートするデーモン。仮想マシン（VM）のファームウェアは OCI 側が管理するため不要です。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;rpcbind.servicerpcbind.socket&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;NFSv3（ネットワークファイルシステム）などで使われる古いポートマップサービス。NFS でストレージをマウントする予定がなければ不要です。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;iscsid.serviceiscsid.socket&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;iSCSI ストレージに接続するためのクアドラント。OCI のブロック・ボリュームを iSCSI 経由で直接マウント（手動アタッチなど）していない限り、標準の準仮想化（Paravirtualized）アタッチであれば不要です。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;udisks2.service&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;主にデスクトップ環境で USB メモリなどのディスクを自動認識・マウントするためのサービス。サーバー用途では不要です。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;停止・無効化のコマンド例&lt;/strong&gt;&lt;br&gt;
単に stop するだけだと再起動時にまた動いてしまうので、disable &amp;ndash;now で自動起動の解除と停止を同時に行います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl disable --now ModemManager fwupd rpcbind rpcbind.socket iscsid iscsid.socket udisks2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="条件付きで停止削除できるサービス効果大"&gt;&lt;a href="#%e6%9d%a1%e4%bb%b6%e4%bb%98%e3%81%8d%e3%81%a7%e5%81%9c%e6%ad%a2%e5%89%8a%e9%99%a4%e3%81%a7%e3%81%8d%e3%82%8b%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e5%8a%b9%e6%9e%9c%e5%a4%a7" class="header-anchor"&gt;&lt;/a&gt;条件付きで停止・削除できるサービス（効果大）
&lt;/h3&gt;&lt;p&gt;環境によっては不要、あるいは別の手段に切り替えることで大幅に軽量化できる重要ポイントです。&lt;/p&gt;
&lt;h4 id="snapdservice--snaporacle-cloud-agent-メモリ節約効果大"&gt;&lt;a href="#snapdservice--snaporacle-cloud-agent-%e3%83%a1%e3%83%a2%e3%83%aa%e7%af%80%e7%b4%84%e5%8a%b9%e6%9e%9c%e5%a4%a7" class="header-anchor"&gt;&lt;/a&gt;&lt;code&gt;snapd.service&lt;/code&gt; / &lt;code&gt;snap.oracle-cloud-agent...&lt;/code&gt; （メモリ節約効果：大）
&lt;/h4&gt;&lt;p&gt;Ubuntu のパッケージ管理システム「Snap」と、OCI の管理エージェントです。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;判断基準&lt;/strong&gt;&lt;br&gt;
OCI のダッシュボードからインスタンスのメトリック（CPU使用率のグラフなど）を見たり、OS の診断機能を使ったりしない、かつ自分で snap コマンドを使ったアプリ（Nextcloud などの Snap版）を動かす予定がない場合。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解説&lt;/strong&gt;&lt;br&gt;
oracle-cloud-agent は便利ですが、メモリが 1GB 以下の環境ではかなりの重荷になります。これらを Snap ごと削除すると、数十MB〜100MB 以上のメモリが浮きます。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;完全に削除する場合のコマンド&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo snap remove oracle-cloud-agent
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt purge snapd -y
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="メモリ使用量の変化"&gt;&lt;a href="#%e3%83%a1%e3%83%a2%e3%83%aa%e4%bd%bf%e7%94%a8%e9%87%8f%e3%81%ae%e5%a4%89%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;メモリ使用量の変化
&lt;/h3&gt;&lt;p&gt;上記のサービスをすべて停止した場合の比較です。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;サービス停止前&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ free -h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; total used free shared buff/cache available
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Mem: 954Mi 360Mi 72Mi 4.9Mi 677Mi 594Mi
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Swap: 2.0Gi 21Mi 2.0Gi
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;サービス停止後&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ free -h
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; total used free shared buff/cache available
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Mem: 954Mi 299Mi 313Mi 4.9Mi 483Mi 655Mi
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Swap: 2.0Gi 10Mi 2.0Gi
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>OCI Bastion 経由でプライベート・サブネット内の Ubuntu インスタンスに SSH で接続</title><link>https://blog.ponkotools.com/posts/2026/05/27/oci-bastion-ubuntu/</link><pubDate>Wed, 27 May 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/05/27/oci-bastion-ubuntu/</guid><description>&lt;p&gt;前回、Oracle Linux インスタンスへ OCI Bastion 経由で SSH 接続する手順を書きました。&lt;/p&gt;
&lt;p&gt;今回は、前回記事で触れた基本的な構成を前提に、Ubuntu インスタンスを対象とした OCI Bastion 経由の SSH 接続手順だけをまとめます。&lt;br&gt;
Oracle Linux と共通する VCN / Bastion の作成や一般的なネットワーク設定は省略し、Ubuntu 固有の注意点に絞って解説します。&lt;/p&gt;
&lt;h2 id="前提"&gt;&lt;a href="#%e5%89%8d%e6%8f%90" class="header-anchor"&gt;&lt;/a&gt;前提
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ターゲット OCI インスタンスには Ubuntu のイメージを使う&lt;/li&gt;
&lt;li&gt;インスタンスは &lt;strong&gt;プライベートサブネット&lt;/strong&gt; に配置し、&lt;strong&gt;パブリックIPなし&lt;/strong&gt; で作成する&lt;/li&gt;
&lt;li&gt;Bastion サービスは事前に作成済みで、プライベートサブネットをターゲットにしている&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ubuntu-でのインスタンス作成時のポイント"&gt;&lt;a href="#ubuntu-%e3%81%a7%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%82%bf%e3%83%b3%e3%82%b9%e4%bd%9c%e6%88%90%e6%99%82%e3%81%ae%e3%83%9d%e3%82%a4%e3%83%b3%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;Ubuntu でのインスタンス作成時のポイント
&lt;/h2&gt;&lt;h3 id="1-イメージに-ubuntu-を選択する"&gt;&lt;a href="#1-%e3%82%a4%e3%83%a1%e3%83%bc%e3%82%b8%e3%81%ab-ubuntu-%e3%82%92%e9%81%b8%e6%8a%9e%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;1. イメージに Ubuntu を選択する
&lt;/h3&gt;&lt;p&gt;インスタンス作成画面のイメージ選択で、&lt;strong&gt;Ubuntu&lt;/strong&gt; を選びます。&lt;br&gt;
OCI の無料枠対象であれば &lt;code&gt;Always Free 適格&lt;/code&gt; のマークを確認してください。&lt;br&gt;
私は今回 &lt;strong&gt;Ubuntu 24.04 Minimal&lt;/strong&gt; を選択しました。&lt;/p&gt;
&lt;h3 id="2-ネットワーキング設定"&gt;&lt;a href="#2-%e3%83%8d%e3%83%83%e3%83%88%e3%83%af%e3%83%bc%e3%82%ad%e3%83%b3%e3%82%b0%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;2. ネットワーキング設定
&lt;/h3&gt;&lt;p&gt;ここは Oracle Linux のときと同じく以下のように設定します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;プライベートサブネットを選択する&lt;/li&gt;
&lt;li&gt;パブリックIP の割当ては &lt;strong&gt;なし&lt;/strong&gt; にする&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SSH キーについても同様です。&lt;/p&gt;
&lt;h2 id="ubuntu-での-bastion-セッション作成"&gt;&lt;a href="#ubuntu-%e3%81%a7%e3%81%ae-bastion-%e3%82%bb%e3%83%83%e3%82%b7%e3%83%a7%e3%83%b3%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;Ubuntu での Bastion セッション作成
&lt;/h2&gt;&lt;p&gt;Bastion 自体は、Oracle Linux のときに作成済みなのでそれを使います。&lt;br&gt;
ただ、セッションの作成方法が異なり、Ubuntu の場合は &lt;strong&gt;管理対象 SSH セッションではなく、SSHポート転送セッションを使う&lt;/strong&gt; のが一般的です。&lt;/p&gt;
&lt;h3 id="bastion-セッションの設定"&gt;&lt;a href="#bastion-%e3%82%bb%e3%83%83%e3%82%b7%e3%83%a7%e3%83%b3%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Bastion セッションの設定
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;OCI コンソールで「アイデンティティとセキュリティ」 &amp;gt; 「要塞（Bastion）」に移動する&lt;/li&gt;
&lt;li&gt;作成した Bastion を選択し、「セッションの作成」をクリックする&lt;/li&gt;
&lt;li&gt;以下のように設定する&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;項目&lt;/th&gt;
 &lt;th&gt;内容&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;セッション・タイプ&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;SSHポート転送セッション&lt;/strong&gt; を選択します。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ターゲット・ホスト&lt;/td&gt;
 &lt;td&gt;Ubuntu インスタンスをIPアドレスまたはインスタンス名で指定します。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;SSH キー&lt;/td&gt;
 &lt;td&gt;ご自身のPCにある SSH 公開鍵をアップロード or ペーストするか、新規に生成します。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="330px" data-flex-grow="137" height="621" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/27/oci-bastion-ubuntu/01.webp" srcset="https://blog.ponkotools.com/posts/2026/05/27/oci-bastion-ubuntu/01_hu_4bf74bb699c3bcbb.webp 800w, https://blog.ponkotools.com/posts/2026/05/27/oci-bastion-ubuntu/01.webp 854w" width="854"&gt;&lt;/p&gt;
&lt;ol start="4"&gt;
&lt;li&gt;「セッションの作成」を実行し、状態が &lt;code&gt;アクティブ&lt;/code&gt; になるまで待つ&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="鍵のパーミッション"&gt;&lt;a href="#%e9%8d%b5%e3%81%ae%e3%83%91%e3%83%bc%e3%83%9f%e3%83%83%e3%82%b7%e3%83%a7%e3%83%b3" class="header-anchor"&gt;&lt;/a&gt;鍵のパーミッション
&lt;/h3&gt;&lt;p&gt;Linux の SSH では秘密鍵の権限が緩いと接続が拒否されます。
以下のように &lt;code&gt;chmod 600&lt;/code&gt; で制限しておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod &lt;span class="m"&gt;600&lt;/span&gt; ~/.ssh/&amp;lt;Ubuntuの秘密鍵&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod &lt;span class="m"&gt;600&lt;/span&gt; ~/.ssh/&amp;lt;セッションの秘密鍵&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="ssh-での接続方法"&gt;&lt;a href="#ssh-%e3%81%a7%e3%81%ae%e6%8e%a5%e7%b6%9a%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;SSH での接続方法
&lt;/h2&gt;&lt;h3 id="方法１"&gt;&lt;a href="#%e6%96%b9%e6%b3%95%ef%bc%91" class="header-anchor"&gt;&lt;/a&gt;方法１
&lt;/h3&gt;&lt;p&gt;Bastion セッションがアクティブになったら、右側のメニューから「SSH コマンドのコピー」を使います。
以下のようなコマンドがコピーされます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -i &amp;lt;privateKey&amp;gt; -N -L &amp;lt;localPort&amp;gt;:10.0.1.203:22 -p &lt;span class="m"&gt;22&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;項目&lt;/th&gt;
 &lt;th&gt;内容&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;&amp;lt;privateKey&amp;gt;&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;セッション作成時の秘密鍵のパスを設定します。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;&amp;lt;localPort&amp;gt;&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;基本的には 「（1024番〜65535番の間であれば）あなたのPCで現在使われていない任意のポート番号」なら何番でも自由 です。&lt;br&gt;よく使われるのは、覚えやすい 12345 や 2222、50022 などだそうです。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;上記を踏まえたうえで、まずは以下のようにコマンドを時刻します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -i ~/.ssh/bastion_id_rsa -N -L 12345:10.0.1.143:22 -p &lt;span class="m"&gt;22&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;すると画面が止まった（待機状態）になります。&lt;br&gt;
これでトンネルが維持されている状態ですので、このターミナル画面は閉じずにそのまま放置してください。&lt;/p&gt;
&lt;p&gt;この状態で新しく別のターミナル画面を開き、以下のコマンドを実行して Ubuntu インスタンスにログインします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -i ~/.ssh/Ubuntu作成時の秘密鍵 -p &lt;span class="m"&gt;12345&lt;/span&gt; ubuntu@localhost
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote class="alert alert-note"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;📝&lt;/span&gt;
 &lt;span class="alert-title"&gt;注記&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;あなたのPCの 12345 番ポート（localhost:12345）に接続することが、そのままトンネルを通じて向こう側のUbuntuに繋がるため、接続先は localhost となります。&lt;br&gt;
OCI の Ubuntu インスタンスのユーザー名は &lt;code&gt;ubuntu&lt;/code&gt; なので、それを指定します。&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;h3 id="方法２"&gt;&lt;a href="#%e6%96%b9%e6%b3%95%ef%bc%92" class="header-anchor"&gt;&lt;/a&gt;方法２
&lt;/h3&gt;&lt;p&gt;前述の方法だとターミナルを２つを使わないといけません。&lt;br&gt;
これをコマンド一発でやる場合、以下のように打ちます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -i &amp;lt;Ubuntuの秘密鍵&amp;gt; -o &lt;span class="nv"&gt;ProxyCommand&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ssh -i &amp;lt;セッションの秘密鍵&amp;gt; -W %h:%p -p 22 ... ubuntu@10.0.1.143
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="方法３"&gt;&lt;a href="#%e6%96%b9%e6%b3%95%ef%bc%93" class="header-anchor"&gt;&lt;/a&gt;方法３
&lt;/h3&gt;&lt;p&gt;上記のコマンドも結局めちゃくちゃ長いので、自分のPCの &lt;code&gt;~/.ssh/config&lt;/code&gt; に設定を書いてしまうのが最もスマートです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;~/.ssh/config&lt;/code&gt; をテキストエディタで開き、以下のように追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 1. Bastion（要塞）自体の設定
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Host oci-bastion
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; HostName host.bastion.....oci.oraclecloud.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Port 22
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # ★セッションを作成するたびに、以下のUser（ocid...の部分）だけ書き換える
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; User ocid1.bastionsession.oc1.....amaaaaaa...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IdentityFile ~/.ssh/セッション作成時の秘密鍵
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 2. ターゲットとなるUbuntuの設定
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Host oci-ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; HostName 10.0.1.143
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; User ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IdentityFile ~/.ssh/Ubuntu作成時の秘密鍵
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ProxyCommand ssh oci-bastion -W %h:%p
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;設定した後は以下のコマンドだけで接続できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh oci-ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、3時間ごとにセッションを作り直した際も、上の User の部分（ocid1.bastionsession&amp;hellip;）だけを書き換えるだけで済みます。&lt;/p&gt;
&lt;p&gt;VS Code の Remote SSH もこれで使えるようになります。&lt;/p&gt;
&lt;h2 id="ubuntu-へのログイン後に確認すること"&gt;&lt;a href="#ubuntu-%e3%81%b8%e3%81%ae%e3%83%ad%e3%82%b0%e3%82%a4%e3%83%b3%e5%be%8c%e3%81%ab%e7%a2%ba%e8%aa%8d%e3%81%99%e3%82%8b%e3%81%93%e3%81%a8" class="header-anchor"&gt;&lt;/a&gt;Ubuntu へのログイン後に確認すること
&lt;/h2&gt;&lt;p&gt;接続に成功すると、プロンプトが次のようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ubuntu@&amp;lt;hostname&amp;gt;:~$
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考"&gt;&lt;a href="#%e5%8f%82%e8%80%83" class="header-anchor"&gt;&lt;/a&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://documentation.ubuntu.com/oracle/oracle-how-to/use-bastion-to-access-VM/" target="_blank" rel="noopener"
 &gt;https://documentation.ubuntu.com/oracle/oracle-how-to/use-bastion-to-access-VM/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.oracle.com/en-us/iaas/Content/Bastion/Tasks/bastionmanaging.htm" target="_blank" rel="noopener"
 &gt;https://docs.oracle.com/en-us/iaas/Content/Bastion/Tasks/bastionmanaging.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://oci-tech.jp/connect-private-compute-via-oci-bastion/" target="_blank" rel="noopener"
 &gt;https://oci-tech.jp/connect-private-compute-via-oci-bastion/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>OCI Bastion 経由でプライベート・サブネット内のインスタンスに SSH で接続</title><link>https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/</link><pubDate>Tue, 26 May 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/</guid><description>&lt;p&gt;日本語では &lt;strong&gt;要塞&lt;/strong&gt; と訳されています。&lt;/p&gt;
&lt;p&gt;手元の PC からこの Bastion（踏み台の役割）を経由させることで、インスタンス自体にパブリックIPを一切持たせないまま、手元の PC のターミナルから直接 SSH 接続できるようになります。&lt;/p&gt;
&lt;p&gt;設定には、ネットワーク（VCN）の構築段階からいくつか重要なポイント（ルーターやセキュリティ・リストの設定など）があり、結構はまったのでメモとして残しておきます。&lt;/p&gt;
&lt;h2 id="仕組みとメリット"&gt;&lt;a href="#%e4%bb%95%e7%b5%84%e3%81%bf%e3%81%a8%e3%83%a1%e3%83%aa%e3%83%83%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;仕組みとメリット
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;完全無料で、自分で踏み台用のサーバー（EC2など）を1台管理・維持する必要がありません。&lt;/li&gt;
&lt;li&gt;接続が必要なときだけ、手元のPCから「3時間だけ有効な一時的な接続セッション（トンネル）」を発行して侵入します。時間が経てば自動で完全に閉じられるため、セキュリティが非常に強固です。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ホストPC: Ubuntu 22.04&lt;/li&gt;
&lt;li&gt;インスタンス: Oracle Linux 9&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class="alert alert-note"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;📝&lt;/span&gt;
 &lt;span class="alert-title"&gt;注記&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;インスタンスが Oracle Linux の場合と、Ubuntu などの他の OS の場合とで方法が一部異なります。&lt;br&gt;
今回は Oracle Linux 9 の場合で、Ubuntu についてはまた別で書きます。&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;h2 id="step1-vcn-とサブネットの作成"&gt;&lt;a href="#step1-vcn-%e3%81%a8%e3%82%b5%e3%83%96%e3%83%8d%e3%83%83%e3%83%88%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;Step1: VCN とサブネットの作成
&lt;/h2&gt;&lt;p&gt;まずは土台となる仮想クラウド・ネットワーク（VCN）を作成します。&lt;br&gt;
手動で細かく作ることもできますが、「VCNウィザード」を使うのが一番簡単で確実です。&lt;br&gt;
インターネットに出るための「インターネット・ゲートウェイ」だけでなく、プライベートVMがアップデート等で外と通信するための「NATゲートウェイ」や「サービス・ゲートウェイ」も自動で作成・紐付けされます。&lt;/p&gt;
&lt;p&gt;OCIコンソールメニューから 「ネットワーキング」 &amp;gt; 「仮想クラウド・ネットワーク」 に移動します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="306px" data-flex-grow="127" height="535" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/01-1.webp" width="683"&gt;&lt;/p&gt;
&lt;p&gt;アクションから「VCNウィザードの起動」 をクリックします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="306px" data-flex-grow="127" height="535" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/01-2.webp" width="683"&gt;&lt;/p&gt;
&lt;p&gt;「インターネット接続性を持つVCNの作成」 を選択し、「VCNウィザードの起動」をクリックします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="420px" data-flex-grow="175" height="677" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/01-3.webp" srcset="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/01-3_hu_eeb952604ff3b7e5.webp 800w, https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/01-3.webp 1187w" width="1187"&gt;&lt;/p&gt;
&lt;p&gt;以下の情報を入力・確認して「次へ」進み、作成します。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;項目&lt;/th&gt;
 &lt;th&gt;内容&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;VCN名&lt;/td&gt;
 &lt;td&gt;任意の名前（例: my-bastion-vcn）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;VCNの構成 CIDRブロック&lt;/td&gt;
 &lt;td&gt;10.0.0.0/16（デフォルトのままでOK）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;パブリック・サブネットのCIDR&lt;/td&gt;
 &lt;td&gt;10.0.0.0/24&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;プライベート・サブネットのCIDR&lt;/td&gt;
 &lt;td&gt;10.0.1.0/24&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="step2-インスタンスの作成"&gt;&lt;a href="#step2-%e3%82%a4%e3%83%b3%e3%82%b9%e3%82%bf%e3%83%b3%e3%82%b9%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;Step2: インスタンスの作成
&lt;/h2&gt;&lt;p&gt;次に、パブリックIPを持たない接続先のインスタンスを作成します。&lt;br&gt;
「コンピュート」 &amp;gt; 「インスタンス」 から 「インスタンスの作成」 をクリックします。&lt;br&gt;
インスタンスの作成については別記事でも書いているので詳細は割愛しますが、イメージは &lt;strong&gt;Oracle Linux 9&lt;/strong&gt; を選びます。&lt;/p&gt;
&lt;p&gt;そして、ネットワーキングセクションで以下を選択します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;プライベート・サブネット（Step 1で作成したもの）を選択。&lt;/li&gt;
&lt;li&gt;「パブリックIPアドレスの割当て」 で 「パブリックIPなし」 を選択。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="270px" data-flex-grow="112" height="1047" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/02-1.webp" srcset="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/02-1_hu_650111b0751cc4fc.webp 800w, https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/02-1.webp 1178w" width="1178"&gt;&lt;/p&gt;
&lt;p&gt;SSHキーのセクションでは、ご自身のPCで作成した公開鍵（.pub）をアップロード、または新規で生成して秘密鍵を保存してください。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="679px" data-flex-grow="282" height="329" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/02-2.webp" srcset="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/02-2_hu_9c0e80c630669994.webp 800w, https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/02-2.webp 931w" width="931"&gt;&lt;/p&gt;
&lt;p&gt;設定したら「作成」をクリックします。&lt;/p&gt;
&lt;h2 id="stes3-bastion-プラグインの有効化-oracle-linux-の場合のみ"&gt;&lt;a href="#stes3-bastion-%e3%83%97%e3%83%a9%e3%82%b0%e3%82%a4%e3%83%b3%e3%81%ae%e6%9c%89%e5%8a%b9%e5%8c%96-oracle-linux-%e3%81%ae%e5%a0%b4%e5%90%88%e3%81%ae%e3%81%bf" class="header-anchor"&gt;&lt;/a&gt;Stes3: Bastion プラグインの有効化 (Oracle Linux の場合のみ)
&lt;/h2&gt;&lt;p&gt;作成したインスタンスの詳細画面に入り、管理タブの「Oracle Cloud エージェント」で要塞を探し、有効化します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="470px" data-flex-grow="196" height="709" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/03.webp" srcset="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/03_hu_3bf5c1beaa28ef3d.webp 800w, https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/03.webp 1391w" width="1391"&gt;&lt;/p&gt;
&lt;p&gt;要塞のステータスが停止済となります。&lt;br&gt;
OSの内部でプログラムのダウンロードや配置が行われており、ステータスが「実行中」になるまでには5分〜10分ほどかかることがあります。&lt;/p&gt;
&lt;blockquote class="alert alert-note"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;📝&lt;/span&gt;
 &lt;span class="alert-title"&gt;注記&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;ここで要塞を有効にしておかないと、後述の管理対象SSHセッションの作成で API エラーとなります。&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;h2 id="step4-bastionの作成"&gt;&lt;a href="#step4-bastion%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;Step4: Bastionの作成
&lt;/h2&gt;&lt;p&gt;「アイデンティティとセキュリティ」 &amp;gt; 「要塞」（Bastion）に移動します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="715px" data-flex-grow="298" height="560" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/04-1.webp" srcset="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/04-1_hu_982245cf6ad2724f.webp 800w, https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/04-1_hu_36b79f883301d695.webp 1600w, https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/04-1.webp 1669w" width="1669"&gt;&lt;/p&gt;
&lt;p&gt;「要塞の作成」 をクリックし、以下のように設定します。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;項目&lt;/th&gt;
 &lt;th&gt;内容&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;要塞名&lt;/td&gt;
 &lt;td&gt;任意の名前&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ターゲット仮想クラウド・ネットワーク&lt;/td&gt;
 &lt;td&gt;Step 1で作成したVCN&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ターゲット・サブネット&lt;/td&gt;
 &lt;td&gt;ターゲットVMがいる「プライベート・サブネット」 を選択します。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;CIDRブロックの許可リスト&lt;/td&gt;
 &lt;td&gt;0.0.0.0/0 （特定のIPだけに絞るとより安全です）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="435px" data-flex-grow="181" height="532" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/04-2.webp" srcset="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/04-2_hu_e3bf1741c390b50c.webp 800w, https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/04-2.webp 965w" width="965"&gt;&lt;/p&gt;
&lt;p&gt;「要塞の作成」をクリックします（アクティブになるまで数分かかります）。&lt;/p&gt;
&lt;h2 id="step5-セッションの作成"&gt;&lt;a href="#step5-%e3%82%bb%e3%83%83%e3%82%b7%e3%83%a7%e3%83%b3%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;Step5: セッションの作成
&lt;/h2&gt;&lt;p&gt;作成した Bastion の詳細画面に入り、「セッションの作成」 をクリックします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="322px" data-flex-grow="134" height="481" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/05-1.webp" width="646"&gt;&lt;/p&gt;
&lt;p&gt;以下のように設定します。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;項目&lt;/th&gt;
 &lt;th&gt;内容&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;セッション・タイプ&lt;/td&gt;
 &lt;td&gt;Oracle Linux の場合は &lt;strong&gt;管理対象SSHセッション&lt;/strong&gt; を選択します。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ユーザー名&lt;/td&gt;
 &lt;td&gt;Oracle Linux の場合は &lt;code&gt;opc&lt;/code&gt; です。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ターゲット・コンピュート・インスタンス&lt;/td&gt;
 &lt;td&gt;Step2 で作成したプライベートVMを選択します。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;SSHキー&lt;/td&gt;
 &lt;td&gt;ご自身のPCにある SSH 公開鍵をアップロード or ペーストするか、新規に生成します。VM作成時に使ったものと同じ、またはペアになるものをアップロードしても OK です（後述）。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="295px" data-flex-grow="123" height="739" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/05-2.webp" srcset="https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/05-2_hu_bdf974789b8dc277.webp 800w, https://blog.ponkotools.com/posts/2026/05/26/oci-bastion/05-2.webp 911w" width="911"&gt;&lt;/p&gt;
&lt;p&gt;「セッションの作成」をクリックします。&lt;br&gt;
状態が作成中となり、しばらく経つとアクティブになります。&lt;/p&gt;
&lt;h2 id="step6-ssh接続の実行"&gt;&lt;a href="#step6-ssh%e6%8e%a5%e7%b6%9a%e3%81%ae%e5%ae%9f%e8%a1%8c" class="header-anchor"&gt;&lt;/a&gt;Step6: SSH接続の実行
&lt;/h2&gt;&lt;p&gt;セッションが「アクティブ」になったら、いよいよ接続です。
作成したセッションの右側にある「3つの点」メニューから 「SSHコマンドのコピー」 をクリックします。&lt;/p&gt;
&lt;p&gt;コピーされるコマンドは以下のような形をしています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -i &amp;lt;privateKey&amp;gt; -o &lt;span class="nv"&gt;ProxyCommand&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ssh -i &amp;lt;privateKey&amp;gt; -W %h:%p -p 22 ocid1.bastionsession.oc1...&amp;#34;&lt;/span&gt; opc@10.0.1.x
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;&amp;lt;privateKey&amp;gt;&lt;/code&gt; 2箇所ありますので、それぞれ VM インスタンス作成時の秘密鍵、Bastion セッション作成時の秘密鍵のパスに変更して実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -i ~/.ssh/VM用の秘密鍵 -o &lt;span class="nv"&gt;ProxyCommand&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ssh -i ~/.ssh/Bastion用の秘密鍵 -W %h:%p ...&amp;#34;&lt;/span&gt; opc@10.0.1.x
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote class="alert alert-note"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;📝&lt;/span&gt;
 &lt;span class="alert-title"&gt;注記&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;セッション作成時の SSH キーを VM 作成時と同じものにした場合は、2箇所とも同じ秘密鍵のパスを指定します。&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;blockquote class="alert alert-note"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;📝&lt;/span&gt;
 &lt;span class="alert-title"&gt;注記&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;Linux のルールとして、秘密鍵の権限が緩いままだとSSH接続が拒否されてしまいます。この場合、以下のコマンドでパーミッションを変更します。&lt;br&gt;
&lt;code&gt;chmod 600 ssh-key-xxxx.key&lt;/code&gt;&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;p&gt;実行すると、Bastionを経由してパブリックIPのないプライベートVMに直接SSHログインが完了します。&lt;/p&gt;
&lt;h2 id="ssh-キーについての補足"&gt;&lt;a href="#ssh-%e3%82%ad%e3%83%bc%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6%e3%81%ae%e8%a3%9c%e8%b6%b3" class="header-anchor"&gt;&lt;/a&gt;SSH キーについての補足
&lt;/h2&gt;&lt;p&gt;セッション作成時のSSHキーはVM作成時と同じでも別のものでも大丈夫です。&lt;/p&gt;
&lt;p&gt;OCI の Bastion サービスは、接続時に「2枚の壁（認証）」を通過するイメージになります。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bastionセッション作成時のSSHキー（壁1：入口の鍵）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ローカルPCから、OCIのBastionサービス（要塞）に侵入するための鍵です。&lt;/li&gt;
&lt;li&gt;Bastionサービス自体が「あなたは本当にこのセッションを作った本人ですか？」を確かめるために使います。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;VM作成時のSSHキー（壁2：奥の部屋の鍵）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bastionを通り抜けたあと、ターゲットのプライベートVMにログインするための鍵です。&lt;/li&gt;
&lt;li&gt;VM（OS）側が「あなたはログインを許可されたユーザーですか？」を確かめるために使います。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;このように鍵の役割が独立しています。&lt;br&gt;
ただ、「同じ鍵」を使った場合と「別の鍵」を使った場合で、最後に実行するSSHコマンドの書き換え方が少し変わります。&lt;/p&gt;
&lt;h3 id="-同じ鍵を使った場合一番シンプル"&gt;&lt;a href="#-%e5%90%8c%e3%81%98%e9%8d%b5%e3%82%92%e4%bd%bf%e3%81%a3%e3%81%9f%e5%a0%b4%e5%90%88%e4%b8%80%e7%95%aa%e3%82%b7%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;① 同じ鍵を使った場合（一番シンプル）
&lt;/h3&gt;&lt;p&gt;すべて1つの秘密鍵（例: id_rsa）で開くので、コピーしたコマンド内の2箇所の &lt;code&gt;&amp;lt;privateKey&amp;gt;&lt;/code&gt; に同じ秘密鍵のパスを指定すればOKです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -i ~/.ssh/id_rsa -o &lt;span class="nv"&gt;ProxyCommand&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ssh -i ~/.ssh/id_rsa -W %h:%p ...&amp;#34;&lt;/span&gt; opc@10.0.1.x
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="-別の鍵を使った場合それぞれ指定が必要"&gt;&lt;a href="#-%e5%88%a5%e3%81%ae%e9%8d%b5%e3%82%92%e4%bd%bf%e3%81%a3%e3%81%9f%e5%a0%b4%e5%90%88%e3%81%9d%e3%82%8c%e3%81%9e%e3%82%8c%e6%8c%87%e5%ae%9a%e3%81%8c%e5%bf%85%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;② 別の鍵を使った場合（それぞれ指定が必要）
&lt;/h3&gt;&lt;p&gt;コマンドの「前半」と「後半」で、それぞれの秘密鍵を指定する必要があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;前半の -i: VM作成時の秘密鍵を指定&lt;/li&gt;
&lt;li&gt;中間の ProxyCommand内の -i: Bastionセッション作成時の秘密鍵を指定&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -i ~/.ssh/VM用の秘密鍵 -o &lt;span class="nv"&gt;ProxyCommand&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ssh -i ~/.ssh/Bastion用の秘密鍵 -W %h:%p ...&amp;#34;&lt;/span&gt; opc@10.0.1.x
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;管理やコマンドの書き換えをシンプルにしたい場合は、「同じ鍵（ペア）」を使ってしまうのが一番迷わなくてラクです。&lt;/p&gt;
&lt;h3 id="セキュリティ的な問題は"&gt;&lt;a href="#%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e7%9a%84%e3%81%aa%e5%95%8f%e9%a1%8c%e3%81%af" class="header-anchor"&gt;&lt;/a&gt;セキュリティ的な問題は？
&lt;/h3&gt;&lt;p&gt;個人開発や一般的な社内検証環境レベルであれば、同じ鍵を使い回しても実用上のセキュリティリスクは非常に低い（実質的に問題ない）と言えます。&lt;/p&gt;
&lt;p&gt;ただし、厳格なエンタープライズ（企業）の運用基準や、セキュリティの理想論（ベストプラクティス）の観点から見ると、いくつか「知っておくべきリスクと理由」があります。&lt;br&gt;
なぜ分けるのが理想とされるのか、その理由は以下です。&lt;/p&gt;
&lt;h4 id="1-鍵が漏洩した際の影響範囲爆発半径が広がる"&gt;&lt;a href="#1-%e9%8d%b5%e3%81%8c%e6%bc%8f%e6%b4%a9%e3%81%97%e3%81%9f%e9%9a%9b%e3%81%ae%e5%bd%b1%e9%9f%bf%e7%af%84%e5%9b%b2%e7%88%86%e7%99%ba%e5%8d%8a%e5%be%84%e3%81%8c%e5%ba%83%e3%81%8c%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;1. 鍵が漏洩した際の影響範囲（爆発半径）が広がる
&lt;/h4&gt;&lt;p&gt;これが最も大きな理由です。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;鍵を分けている場合：&lt;/strong&gt;
もしBastion用の鍵が外部に漏れても、攻撃者はBastionの入り口までしか来られません。ターゲットVMの鍵が無事なら、中のデータにはアクセスできません。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;同じ鍵を使っている場合：&lt;/strong&gt;
その1つの秘密鍵が漏洩した瞬間、Bastionの突破からターゲットVMへのログインまで、すべての防御壁が同時に崩壊します。&lt;/p&gt;
&lt;p&gt;ひとつの鍵にすべての権限を持たせることは、セキュリティの世界で嫌がられる「単一障害点（Single Point of Failure）」を作ることになってしまいます。&lt;/p&gt;
&lt;h4 id="2-誰がどこにアクセスしたかの監査ログが曖昧になる"&gt;&lt;a href="#2-%e8%aa%b0%e3%81%8c%e3%81%a9%e3%81%93%e3%81%ab%e3%82%a2%e3%82%af%e3%82%bb%e3%82%b9%e3%81%97%e3%81%9f%e3%81%8b%e3%81%ae%e7%9b%a3%e6%9f%bb%e3%83%ad%e3%82%b0%e3%81%8c%e6%9b%96%e6%98%a7%e3%81%ab%e3%81%aa%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;2. 「誰が・どこに」アクセスしたかの監査（ログ）が曖昧になる
&lt;/h4&gt;&lt;p&gt;本番環境やチーム開発において重要な視点です。&lt;/p&gt;
&lt;p&gt;Bastion（要塞）の本来の目的は、「いつ、誰が、どのサーバーに入ったか」を厳密に記録・コントロールすることです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bastion用の鍵： 「あなたがクラウド環境のネットワークに入った」ことを証明する&lt;/li&gt;
&lt;li&gt;VM用の鍵： 「あなたが特定のサーバーの opc ユーザーとしてログインした」ことを証明する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これらを同じ鍵にしてしまうと、鍵の管理者が同一人物である前提になってしまい、「Bastionを通過した人と、実際にVMを操作した人が本当に同一人物か？」という厳密なトレース（監査ログの信頼性）が担保しにくくなります。&lt;/p&gt;
&lt;h2 id="参考"&gt;&lt;a href="#%e5%8f%82%e8%80%83" class="header-anchor"&gt;&lt;/a&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://documentation.ubuntu.com/oracle/oracle-how-to/use-bastion-to-access-VM/" target="_blank" rel="noopener"
 &gt;https://documentation.ubuntu.com/oracle/oracle-how-to/use-bastion-to-access-VM/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://techblog.ap-com.co.jp/entry/2025/03/19/132232" target="_blank" rel="noopener"
 &gt;https://techblog.ap-com.co.jp/entry/2025/03/19/132232&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://oci-tech.jp/connect-private-compute-via-oci-bastion/" target="_blank" rel="noopener"
 &gt;https://oci-tech.jp/connect-private-compute-via-oci-bastion/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/rieto/items/3fcdd5d5157ecb406719" target="_blank" rel="noopener"
 &gt;https://qiita.com/rieto/items/3fcdd5d5157ecb406719&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>OCI (Oracle Cloud Infrastructure) で VM インスタンスを作成する</title><link>https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/</link><pubDate>Thu, 21 May 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/</guid><description>&lt;h2 id="oci-oracle-cloud-infrastructure"&gt;&lt;a href="#oci-oracle-cloud-infrastructure" class="header-anchor"&gt;&lt;/a&gt;OCI (Oracle Cloud Infrastructure)
&lt;/h2&gt;&lt;p&gt;OCI には &lt;strong&gt;Always Free（永久無料枠）&lt;/strong&gt; という非常に強力な特典があり、&lt;strong&gt;4 OCPU / 24 GB メモリ&lt;/strong&gt; という、他社クラウドであれば有料級のハイスペックな Arm サーバー（Ampere A1）を無料で 24時間365日動かすことができます。&lt;/p&gt;
&lt;h3 id="oci-のコンピュート環境vm-とコンテナインスタンスの違い"&gt;&lt;a href="#oci-%e3%81%ae%e3%82%b3%e3%83%b3%e3%83%94%e3%83%a5%e3%83%bc%e3%83%88%e7%92%b0%e5%a2%83vm-%e3%81%a8%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e3%82%a4%e3%83%b3%e3%82%b9%e3%82%bf%e3%83%b3%e3%82%b9%e3%81%ae%e9%81%95%e3%81%84" class="header-anchor"&gt;&lt;/a&gt;OCI のコンピュート環境：VM とコンテナインスタンスの違い
&lt;/h3&gt;&lt;p&gt;OCI でアプリケーションを動かすアプローチとして、主に &lt;strong&gt;「VM Compute（仮想マシン）」&lt;/strong&gt; と &lt;strong&gt;「コンテナインスタンス（Container Instances）」&lt;/strong&gt; の 2つがあります。&lt;/p&gt;
&lt;p&gt;どちらも Docker コンテナを動かせますが、その管理レイヤーと仕様には明確な違いがあります。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;比較項目&lt;/th&gt;
 &lt;th style="text-align: left"&gt;VM Compute (仮想マシン)&lt;/th&gt;
 &lt;th style="text-align: left"&gt;コンテナインスタンス&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;管理の単位&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;OS（Linux / Windows）&lt;/td&gt;
 &lt;td style="text-align: left"&gt;コンテナ（Dockerイメージなど）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;インフラ管理&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;必要&lt;/strong&gt;（OSアップデート、SSH管理）&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;不要&lt;/strong&gt;（サーバーレス。オラクルが基盤を管理）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;起動スピード&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;数分（OSのブート時間必要）&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;数秒&lt;/strong&gt;（コンテナの起動のみ）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;永続ストレージ&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ブロック・ボリュームを自由に追加・マウント可能&lt;/td&gt;
 &lt;td style="text-align: left"&gt;エフェメラル（一時的。再起動でデータ消滅）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;永久無料枠&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;あり（4 OCPU / 24 GBメモリまで無料）&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;なし（秒単位の従量課金）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="どちらを選ぶべきか"&gt;&lt;a href="#%e3%81%a9%e3%81%a1%e3%82%89%e3%82%92%e9%81%b8%e3%81%b6%e3%81%b9%e3%81%8d%e3%81%8b" class="header-anchor"&gt;&lt;/a&gt;どちらを選ぶべきか？
&lt;/h3&gt;&lt;p&gt;コンテナインスタンスはサーバーレスで運用が手軽ですが、永久無料枠（Always Free）の対象外となります。また、コンテナの再起動によって内部のデータが消去される特性を持ちます。&lt;/p&gt;
&lt;p&gt;そのため、&lt;strong&gt;「24時間いつでも無料で動かし続けたい」「生成されるログやデータをローカルディスクに安全に保持（永続化）したい」という場合は、VM Compute を選択するのが最適&lt;/strong&gt;です。&lt;/p&gt;
&lt;h2 id="oci-への登録"&gt;&lt;a href="#oci-%e3%81%b8%e3%81%ae%e7%99%bb%e9%8c%b2" class="header-anchor"&gt;&lt;/a&gt;OCI への登録
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://www.oracle.com/jp/cloud/free/" target="_blank" rel="noopener"
 &gt;https://www.oracle.com/jp/cloud/free/&lt;/a&gt; にアクセスして「無料で始める」をクリックして各種情報を入力します。&lt;br&gt;
ちょっとした注意事項として、住所は英語で入力する必要があります。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;参考&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://tzang.net/ja/oci-apply/" target="_blank" rel="noopener"
 &gt;https://tzang.net/ja/oci-apply/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://techblog.ap-com.co.jp/entry/2024/09/06/093000" target="_blank" rel="noopener"
 &gt;https://techblog.ap-com.co.jp/entry/2024/09/06/093000&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/kamimachi06/items/c72ac35600c0597d4524" target="_blank" rel="noopener"
 &gt;https://qiita.com/kamimachi06/items/c72ac35600c0597d4524&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="インスタンスの作成"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%82%bf%e3%83%b3%e3%82%b9%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;インスタンスの作成
&lt;/h2&gt;&lt;p&gt;ホームより &lt;strong&gt;インスタンス&lt;/strong&gt; を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="607px" data-flex-grow="253" height="472" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/01.webp" srcset="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/01_hu_e693b17eecf5f133.webp 800w, https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/01.webp 1195w" width="1195"&gt;&lt;/p&gt;
&lt;p&gt;ホームにない場合は、左上のメニューから &lt;strong&gt;コンピュート &amp;gt; インスタンス&lt;/strong&gt; でも OK です。&lt;/p&gt;
&lt;p&gt;続いて &lt;strong&gt;インスタンスの作成&lt;/strong&gt; を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="402px" data-flex-grow="167" height="599" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/02.webp" srcset="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/02_hu_2a5b52be3f71e459.webp 800w, https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/02.webp 1005w" width="1005"&gt;&lt;/p&gt;
&lt;h3 id="基本情報"&gt;&lt;a href="#%e5%9f%ba%e6%9c%ac%e6%83%85%e5%a0%b1" class="header-anchor"&gt;&lt;/a&gt;基本情報
&lt;/h3&gt;&lt;h4 id="イメージ"&gt;&lt;a href="#%e3%82%a4%e3%83%a1%e3%83%bc%e3%82%b8" class="header-anchor"&gt;&lt;/a&gt;イメージ
&lt;/h4&gt;&lt;p&gt;デフォルトでは Oracle linux になっています。&lt;br&gt;
Oracle Linux は Red Hat Enterprise Linux（RHEL）をベースにした OS だそうです。&lt;/p&gt;
&lt;p&gt;セキュリティの「保護インスタンス」は、仮想マシン（VM）の乗っ取りや、悪意のあるプログラムによるOS改ざんを防ぐための「セキュリティ強化機能が有効になっている状態」を指すそうですので、保護インスタンスになっているものを選択しておいたほうが良さそうです。&lt;/p&gt;
&lt;h4 id="シェイプ"&gt;&lt;a href="#%e3%82%b7%e3%82%a7%e3%82%a4%e3%83%97" class="header-anchor"&gt;&lt;/a&gt;シェイプ
&lt;/h4&gt;&lt;p&gt;Always Free 対象のものとして以下の２つがあります。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;項目&lt;/th&gt;
 &lt;th&gt;Ampere (A1.Flex)&lt;/th&gt;
 &lt;th&gt;AMD (E2.1.Micro)&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;最大リソース&lt;/td&gt;
 &lt;td&gt;4 OCPU / 24 GB（分配可能）&lt;/td&gt;
 &lt;td&gt;1 OCPU / 1 GB × 2台&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;アーキテクチャ&lt;/td&gt;
 &lt;td&gt;Arm (aarch64)&lt;/td&gt;
 &lt;td&gt;x86_64&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;主な用途&lt;/td&gt;
 &lt;td&gt;開発環境、Docker、高負荷な処理、Webサーバー&lt;/td&gt;
 &lt;td&gt;軽量なスクリプト実行、VPNサーバー、検証用&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;VM.Standard.A1.Flex&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;現在OCIで提供されている中で最もハイスペックかつ使い勝手の良い無料枠インスタンスです。&lt;br&gt;
&lt;strong&gt;Ampere&lt;/strong&gt; を選択し、&lt;strong&gt;VM.Standard.A1.Flex&lt;/strong&gt; をチェックします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="467px" data-flex-grow="194" height="666" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/03-1.webp" srcset="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/03-1_hu_f43726e3dff82e49.webp 800w, https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/03-1.webp 1296w" width="1296"&gt;&lt;/p&gt;
&lt;p&gt;シェイプ名横の ▼ を押すと CPU と RAM の設定ができます。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="455px" data-flex-grow="189" height="570" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/03-3.webp" srcset="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/03-3_hu_cb161b4a08e3cb5b.webp 800w, https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/03-3.webp 1082w" width="1082"&gt;&lt;/p&gt;
&lt;p&gt;「4 OCPU / 24 GB」までは無料で使えるらしいです。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;VM.Standard.E2.1.Micro&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ampere A1 は人気のため、空きがなくて作成できないことが多いです。&lt;br&gt;
また、システムが Arm（Aarch64）アーキテクチャに対応しておらず、どうしても従来の x86_64 環境が必要な場合もあったりします。&lt;br&gt;
そのような場合はこちらを選びます。&lt;br&gt;
ただし、スペックは Ampere A1 に比べて大幅に低くなります。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;専門と前世代&lt;/strong&gt; を選択し、&lt;strong&gt;VM.Standard.E2.1.Micro&lt;/strong&gt; をチェックします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="411px" data-flex-grow="171" height="762" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/03-2.webp" srcset="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/03-2_hu_948bb4cca6084069.webp 800w, https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/03-2.webp 1306w" width="1306"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;上記のうち好きな方を選び、次へを押します。&lt;/p&gt;
&lt;h3 id="セキュリティ"&gt;&lt;a href="#%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3" class="header-anchor"&gt;&lt;/a&gt;セキュリティ
&lt;/h3&gt;&lt;p&gt;保護インスタンスの設定ができますが、予期せぬエラーや「動かない」トラブルの原因になりやすいそうなので、今回は OFF のままとしました。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="506px" data-flex-grow="211" height="548" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/05.webp" srcset="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/05_hu_5e0e0a49f3828ea0.webp 800w, https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/05.webp 1157w" width="1157"&gt;&lt;/p&gt;
&lt;h3 id="ネットワーキング"&gt;&lt;a href="#%e3%83%8d%e3%83%83%e3%83%88%e3%83%af%e3%83%bc%e3%82%ad%e3%83%b3%e3%82%b0" class="header-anchor"&gt;&lt;/a&gt;ネットワーキング
&lt;/h3&gt;&lt;h4 id="プライマリvnic"&gt;&lt;a href="#%e3%83%97%e3%83%a9%e3%82%a4%e3%83%9e%e3%83%aavnic" class="header-anchor"&gt;&lt;/a&gt;プライマリVNIC
&lt;/h4&gt;&lt;p&gt;初めて OCI を使うので、まだ「既存のネットワーク」が存在しないため、新しく &lt;strong&gt;新規仮想クラウド・ネットワーク&lt;/strong&gt; を選択します。
サブネットも自動的に &lt;strong&gt;新規パブリック・サブネットの作成&lt;/strong&gt; に切り替わり、名前などが自動入力されます。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="392px" data-flex-grow="163" height="708" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/06-1.webp" srcset="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/06-1_hu_8ff9b9a5a1b5b81a.webp 800w, https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/06-1.webp 1158w" width="1158"&gt;&lt;/p&gt;
&lt;p&gt;２回目は既存のネットワークを選択すれば OK です。&lt;/p&gt;
&lt;h4 id="パブリックipv4アドレス割当て"&gt;&lt;a href="#%e3%83%91%e3%83%96%e3%83%aa%e3%83%83%e3%82%afipv4%e3%82%a2%e3%83%89%e3%83%ac%e3%82%b9%e5%89%b2%e5%bd%93%e3%81%a6" class="header-anchor"&gt;&lt;/a&gt;パブリックIPv4アドレス割当て
&lt;/h4&gt;&lt;p&gt;今回は外部からの通信（インバウンド）を受ける必要はないため、 &lt;strong&gt;パブリックIPv4アドレスの割当て&lt;/strong&gt; は &lt;strong&gt;OFF&lt;/strong&gt; にしておきました。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="317px" data-flex-grow="132" height="879" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/06-2.webp" srcset="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/06-2_hu_2a95284a5cafcb5f.webp 800w, https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/06-2.webp 1162w" width="1162"&gt;&lt;/p&gt;
&lt;h4 id="sshキーの追加"&gt;&lt;a href="#ssh%e3%82%ad%e3%83%bc%e3%81%ae%e8%bf%bd%e5%8a%a0" class="header-anchor"&gt;&lt;/a&gt;SSHキーの追加
&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;キー・ペアを自動で生成&lt;/strong&gt; を選択し、&lt;strong&gt;秘密キーのダウンロード&lt;/strong&gt; を押して秘密鍵をダウンロードしておきます。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="714px" data-flex-grow="297" height="330" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/06-3.webp" srcset="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/06-3_hu_65217d3dc1d492e2.webp 800w, https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/06-3.webp 982w" width="982"&gt;&lt;/p&gt;
&lt;blockquote class="alert alert-note"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;📝&lt;/span&gt;
 &lt;span class="alert-title"&gt;注記&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;SSH キーなしを選択すると、後述するように Cloud Shell からもインスタンスにアクセスできませんでした。
外部から SSH でアクセスする予定がなくても SSH キーは作成しておかないといけないようです。&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;h3 id="ストレージ"&gt;&lt;a href="#%e3%82%b9%e3%83%88%e3%83%ac%e3%83%bc%e3%82%b8" class="header-anchor"&gt;&lt;/a&gt;ストレージ
&lt;/h3&gt;&lt;p&gt;ここは全てデフォルトのままとしました。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="449px" data-flex-grow="187" height="631" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/07.webp" srcset="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/07_hu_950aba20468a9cd0.webp 800w, https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/07.webp 1182w" width="1182"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;「カスタム・ブート・ボリューム・サイズ&amp;hellip;」について&lt;/strong&gt;
チェックがOFF（デフォルト）の場合、標準サイズである 46.6 GB のディスクが自動で割り当てられます。&lt;br&gt;
OCIの無料枠では最大で合計200GBまでストレージが使え、ここにチェックを入れて数値を 100 や 200 に増やすことも可能です。&lt;br&gt;
ただ、後からでもディスクサイズは簡単に拡張できるため、最初はデフォルトのままで様子見するのが安全です。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;「転送中暗号化の使用」について&lt;/strong&gt;
デフォルトでONになっていますが、これは「仮想マシンとストレージの間の通信を暗号化して盗聴を防ぐ」というインフラ側の高度な保護機能です。&lt;br&gt;
パフォーマンスへの影響も無視できるレベルですので、ON（今の状態）のままにしておきましょう。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;「自分が管理するキーでこのボリュームを暗号化」について&lt;/strong&gt;
チェックがOFF（デフォルト）の場合、Oracleが管理する標準の暗号鍵で自動的にディスクが暗号化されます。&lt;br&gt;
個人開発で自前の鍵管理（Vault/KMSなど）を入れると管理コストが増えて複雑になるため、OFFのままで問題ありません。&lt;/p&gt;
&lt;h3 id="作成"&gt;&lt;a href="#%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;作成
&lt;/h3&gt;&lt;p&gt;次へ進み、&lt;strong&gt;「作成」&lt;/strong&gt; を押すとインスタンスが作成されます。&lt;br&gt;
しばらく待つとインスタンスが作成されます（ステータス表示が &lt;strong&gt;実行中&lt;/strong&gt; に変わります）。&lt;/p&gt;
&lt;h3 id="api-エラーが発生した場合"&gt;&lt;a href="#api-%e3%82%a8%e3%83%a9%e3%83%bc%e3%81%8c%e7%99%ba%e7%94%9f%e3%81%97%e3%81%9f%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;API エラーが発生した場合
&lt;/h3&gt;&lt;p&gt;これは設定の間違いではなく、「現在、Oracleのデータセンター側で、無料枠用のArmサーバー（Ampere）の在庫が一時的に切れている」 という、OCIの無料枠で最も頻繁に発生する有名な現象です。&lt;br&gt;
世界中で無料枠のAmpereは非常に人気があるため、椅子取りゲームのようになっています。&lt;/p&gt;
&lt;p&gt;解決策は以下です。&lt;/p&gt;
&lt;h4 id="1x86のamd枠に切り替えて即時作成する確実おすすめ"&gt;&lt;a href="#1x86%e3%81%aeamd%e6%9e%a0%e3%81%ab%e5%88%87%e3%82%8a%e6%9b%bf%e3%81%88%e3%81%a6%e5%8d%b3%e6%99%82%e4%bd%9c%e6%88%90%e3%81%99%e3%82%8b%e7%a2%ba%e5%ae%9f%e3%81%8a%e3%81%99%e3%81%99%e3%82%81" class="header-anchor"&gt;&lt;/a&gt;1：x86の「AMD枠」に切り替えて即時作成する（確実・おすすめ）
&lt;/h4&gt;&lt;p&gt;Arm（Ampere）の在庫がなくても、もう1つの無料枠であるAMD（VM.Standard.E2.1.Micro）であれば、在庫に余裕がありすんなり作成できるケースが非常に多いです。&lt;/p&gt;
&lt;h4 id="2フォルトドメインを変更して再トライする"&gt;&lt;a href="#2%e3%83%95%e3%82%a9%e3%83%ab%e3%83%88%e3%83%89%e3%83%a1%e3%82%a4%e3%83%b3%e3%82%92%e5%a4%89%e6%9b%b4%e3%81%97%e3%81%a6%e5%86%8d%e3%83%88%e3%83%a9%e3%82%a4%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;2：「フォルト・ドメイン」を変更して再トライする
&lt;/h4&gt;&lt;p&gt;同じAmpere（Arm）のまま、サーバーが置かれる物理的な区画（フォルト・ドメイン）を変更することで、運よく在庫が引っかかることがあります。&lt;/p&gt;
&lt;h4 id="3数日数週間時間を変えてクリックし続ける"&gt;&lt;a href="#3%e6%95%b0%e6%97%a5%e6%95%b0%e9%80%b1%e9%96%93%e6%99%82%e9%96%93%e3%82%92%e5%a4%89%e3%81%88%e3%81%a6%e3%82%af%e3%83%aa%e3%83%83%e3%82%af%e3%81%97%e7%b6%9a%e3%81%91%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;3：数日〜数週間、時間を変えてクリックし続ける
&lt;/h4&gt;&lt;p&gt;どうしても強力な「Arm（4 OCPU / 24 GBを狙いたいなど）」が良い場合、誰かがインスタンスを削除して在庫が空くのを待つことになります。&lt;/p&gt;
&lt;h2 id="インスタンスの起動"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%82%bf%e3%83%b3%e3%82%b9%e3%81%ae%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;インスタンスの起動
&lt;/h2&gt;&lt;p&gt;コンピュートの画面から &lt;strong&gt;インスタンス&lt;/strong&gt; を選択し、該当のインスタンスをクリックします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="591px" data-flex-grow="246" height="438" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/08-1.webp" srcset="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/08-1_hu_4c5916a94a5f5af9.webp 800w, https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/08-1.webp 1080w" width="1080"&gt;&lt;/p&gt;
&lt;p&gt;右上から起動を押します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="593px" data-flex-grow="247" height="327" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/08-2.webp" srcset="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/08-2_hu_341b4d1921dff504.webp 800w, https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/08-2.webp 808w" width="808"&gt;&lt;/p&gt;
&lt;p&gt;これでしばらく待つとインスタンスが起動します。&lt;/p&gt;
&lt;h2 id="インスタンスへ接続cloud-shell-で接続"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%82%bf%e3%83%b3%e3%82%b9%e3%81%b8%e6%8e%a5%e7%b6%9acloud-shell-%e3%81%a7%e6%8e%a5%e7%b6%9a" class="header-anchor"&gt;&lt;/a&gt;インスタンスへ接続（Cloud Shell で接続）
&lt;/h2&gt;&lt;p&gt;OCI 上から Cloud Shell でインスタンスに接続してみます。&lt;/p&gt;
&lt;h3 id="cloud-shell-の起動"&gt;&lt;a href="#cloud-shell-%e3%81%ae%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;Cloud Shell の起動
&lt;/h3&gt;&lt;p&gt;画面右上の &lt;strong&gt;開発者ツール&lt;/strong&gt; をクリックし、&lt;strong&gt;Cloud Shell&lt;/strong&gt; を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="483px" data-flex-grow="201" height="141" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/10-1.webp" width="284"&gt;&lt;/p&gt;
&lt;p&gt;画面下に端末が表示されますが、まだインスタンスの中には入っていません。&lt;br&gt;
Cloud Shell が単体で起動しただけです。&lt;/p&gt;
&lt;h3 id="ネットワークの変更"&gt;&lt;a href="#%e3%83%8d%e3%83%83%e3%83%88%e3%83%af%e3%83%bc%e3%82%af%e3%81%ae%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;ネットワークの変更
&lt;/h3&gt;&lt;p&gt;端末上部の「ネットワーク：パブリック」と表示されたプルダウンから「エフェメラル・プライベートネット・・・」を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="402px" data-flex-grow="167" height="192" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/10-2.webp" width="322"&gt;&lt;/p&gt;
&lt;p&gt;インスタンス作成時に作成した VCN とサブネットを選択し、&lt;strong&gt;アクティブなネットワークとして使用&lt;/strong&gt; を押します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="273px" data-flex-grow="114" height="538" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/21/oracle-cloud-infrastructure/10-3.webp" width="614"&gt;&lt;/p&gt;
&lt;h3 id="秘密鍵ファイルのアップロード"&gt;&lt;a href="#%e7%a7%98%e5%af%86%e9%8d%b5%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ae%e3%82%a2%e3%83%83%e3%83%97%e3%83%ad%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;秘密鍵ファイルのアップロード
&lt;/h3&gt;&lt;p&gt;先程ダウンロードした秘密鍵ファイルを端末上にドラッグ＆ドロップしてアップロードします。&lt;/p&gt;
&lt;p&gt;Linux のルールとして、秘密鍵の権限が緩いままだとSSH接続が拒否されてしまうため、以下のコマンドでパーミッションを変更します。
（※ファイル名はご自身のものに書き換えてください）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod 600 ssh-key-xxxx.key
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ssh-コマンドでログインする"&gt;&lt;a href="#ssh-%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e3%81%a7%e3%83%ad%e3%82%b0%e3%82%a4%e3%83%b3%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;SSH コマンドでログインする
&lt;/h3&gt;&lt;p&gt;以上で準備は完了です。&lt;br&gt;
以下のコマンドで Cloud Shell インスタンスへと接続します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -i ssh-key-xxxx.key &amp;lt;username&amp;gt;@&amp;lt;private_ip_address&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;&amp;lt;username&amp;gt;&lt;/code&gt; は、インスタンスのデフォルトのユーザー名です。&lt;br&gt;
Oracle Linux および Redhat Enterprise Linux 互換イメージの場合、デフォルトのユーザー名は &lt;code&gt;opc&lt;/code&gt;、Ubuntu イメージの場合、デフォルトのユーザー名は &lt;code&gt;ubuntu&lt;/code&gt; だそうです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;private_ip_address&amp;gt;&lt;/code&gt; は接続先インスタンスのプライベートIPアドレスです。&lt;br&gt;
&lt;strong&gt;コンピュート &amp;gt; インスタンス&lt;/strong&gt; で確認できます。&lt;code&gt;10.0.x.x&lt;/code&gt; のような数字を入れてください。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px"&gt;&lt;/p&gt;
&lt;p&gt;コマンド入力後、&lt;code&gt;Are you sure you want to continue connecting (yes/no)?&lt;/code&gt; と聞かれたら、 &lt;code&gt;yes&lt;/code&gt; と入力してEnterを押します。&lt;/p&gt;
&lt;p&gt;無事にプロンプトが &lt;code&gt;&amp;lt;username&amp;gt;@instance-xxxx:~$&lt;/code&gt; に切り替われば、インスタンスに接続できています。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;とりあえずはここまで。&lt;/p&gt;
&lt;h2 id="参考"&gt;&lt;a href="#%e5%8f%82%e8%80%83" class="header-anchor"&gt;&lt;/a&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.clinks.jp/column/oci/1983/" target="_blank" rel="noopener"
 &gt;https://www.clinks.jp/column/oci/1983/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://oracle-japan.github.io/ocitutorials/beginners/creating-compute-instance/" target="_blank" rel="noopener"
 &gt;https://oracle-japan.github.io/ocitutorials/beginners/creating-compute-instance/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.reqtc.com/blog/oci-ssh.html" target="_blank" rel="noopener"
 &gt;https://www.reqtc.com/blog/oci-ssh.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Cloudflare Pages で静的サイトを公開する（GitLab 連携）</title><link>https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/</link><pubDate>Sun, 17 May 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/</guid><description>&lt;h2 id="前提環境"&gt;&lt;a href="#%e5%89%8d%e6%8f%90%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;前提・環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ソース管理: &lt;strong&gt;GitLab&lt;/strong&gt; (GitHub でもやり方は同じ)&lt;/li&gt;
&lt;li&gt;ホスティング: &lt;strong&gt;Cloudflare Pages&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;DNS: &lt;strong&gt;Cloudflare&lt;/strong&gt;（既存ドメインのサブドメインに展開する想定）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="gitlab-側で必要なこと"&gt;&lt;a href="#gitlab-%e5%81%b4%e3%81%a7%e5%bf%85%e8%a6%81%e3%81%aa%e3%81%93%e3%81%a8" class="header-anchor"&gt;&lt;/a&gt;GitLab 側で必要なこと
&lt;/h2&gt;&lt;p&gt;ほぼ何もしなくて構いません。&lt;br&gt;
&lt;code&gt;.gitlab-ci.yml&lt;/code&gt; を書く必要はなく、Cloudflare Pages が直接 git clone してビルドします。&lt;/p&gt;
&lt;p&gt;最低限の準備は次のとおりです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;リポジトリが Cloudflare からアクセスできること（Public ならそのまま、Private なら次節の OAuth で許可します）&lt;/li&gt;
&lt;li&gt;プロダクションブランチ（&lt;code&gt;main&lt;/code&gt; など）を決めておくこと&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ブランチ運用は Cloudflare Pages 側で自動的に処理されます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;プロダクションブランチへの push → 本番デプロイ&lt;/li&gt;
&lt;li&gt;それ以外のブランチへの push → &lt;strong&gt;自動でプレビュー URL が発行される&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="cloudflare-pages-側のセットアップ"&gt;&lt;a href="#cloudflare-pages-%e5%81%b4%e3%81%ae%e3%82%bb%e3%83%83%e3%83%88%e3%82%a2%e3%83%83%e3%83%97" class="header-anchor"&gt;&lt;/a&gt;Cloudflare Pages 側のセットアップ
&lt;/h2&gt;&lt;p&gt;Cloudflare ダッシュボード → &lt;strong&gt;Workers &amp;amp; Pages&lt;/strong&gt; を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="519px" data-flex-grow="216" height="536" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/01.webp" srcset="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/01_hu_9ea2c901c150fda5.webp 800w, https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/01.webp 1160w" width="1160"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Create application&lt;/strong&gt; を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="529px" data-flex-grow="220" height="529" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/02.webp" srcset="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/02_hu_a08f49e8f9b7bb41.webp 800w, https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/02.webp 1167w" width="1167"&gt;&lt;/p&gt;
&lt;p&gt;下部にある &lt;strong&gt;Get started&lt;/strong&gt; をクリックします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="518px" data-flex-grow="216" height="434" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/03.webp" srcset="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/03_hu_6c3acff843249430.webp 800w, https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/03.webp 938w" width="938"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Import an existing Git repository&lt;/strong&gt; の &lt;strong&gt;Get started&lt;/strong&gt; を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="443px" data-flex-grow="184" height="332" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/04.webp" width="614"&gt;&lt;/p&gt;
&lt;h3 id="git-プロバイダの接続"&gt;&lt;a href="#git-%e3%83%97%e3%83%ad%e3%83%90%e3%82%a4%e3%83%80%e3%81%ae%e6%8e%a5%e7%b6%9a" class="header-anchor"&gt;&lt;/a&gt;Git プロバイダの接続
&lt;/h3&gt;&lt;p&gt;GitHub だけでなく &lt;strong&gt;GitLab も公式サポート&lt;/strong&gt;されています。&lt;br&gt;
&lt;strong&gt;GitLab&lt;/strong&gt; のタブを選択し、&lt;strong&gt;Connect GitLab&lt;/strong&gt; から OAuth で認証を行います。&lt;br&gt;
認証後、対象リポジトリを選び、&lt;strong&gt;Begin setup&lt;/strong&gt; を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="415px" data-flex-grow="173" height="549" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/05.webp" srcset="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/05_hu_29852ce65aaaecb.webp 800w, https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/05.webp 951w" width="951"&gt;&lt;/p&gt;
&lt;h3 id="ビルド設定で指定する項目"&gt;&lt;a href="#%e3%83%93%e3%83%ab%e3%83%89%e8%a8%ad%e5%ae%9a%e3%81%a7%e6%8c%87%e5%ae%9a%e3%81%99%e3%82%8b%e9%a0%85%e7%9b%ae" class="header-anchor"&gt;&lt;/a&gt;ビルド設定で指定する項目
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Framework preset&lt;/strong&gt;: 使っているフレームワークに該当があれば選びます。自前のシェルスクリプトでビルドするなら None で構いません&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build command&lt;/strong&gt;: リポジトリ直下から実行されるビルドコマンド&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build output directory&lt;/strong&gt;: 成果物のディレクトリ（例: &lt;code&gt;dist&lt;/code&gt;、&lt;code&gt;public&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Root directory&lt;/strong&gt;: 通常は空欄でリポジトリ直下&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environment variables&lt;/strong&gt;: 必要に応じて設定します&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="286px" data-flex-grow="119" height="785" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/06.webp" srcset="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/06_hu_7c9afe961a914c17.webp 800w, https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/06.webp 936w" width="936"&gt;&lt;/p&gt;
&lt;h3 id="初回デプロイの確認"&gt;&lt;a href="#%e5%88%9d%e5%9b%9e%e3%83%87%e3%83%97%e3%83%ad%e3%82%a4%e3%81%ae%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;初回デプロイの確認
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Save and Deploy&lt;/strong&gt; を選択すると数分でビルドが走り、プレビュー URL（&lt;code&gt;&amp;lt;project&amp;gt;.pages.dev&lt;/code&gt;）が発行されます。&lt;br&gt;
ここでまず動作確認をしてから、カスタムドメインを当てに行きます。&lt;/p&gt;
&lt;h2 id="カスタムドメインの設定"&gt;&lt;a href="#%e3%82%ab%e3%82%b9%e3%82%bf%e3%83%a0%e3%83%89%e3%83%a1%e3%82%a4%e3%83%b3%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;カスタムドメインの設定
&lt;/h2&gt;&lt;p&gt;DNS も Cloudflare で管理しているなら、ほぼワンクリックで終わります。&lt;/p&gt;
&lt;p&gt;初回デプロイ完了後、&lt;strong&gt;Add custom domain&lt;/strong&gt; を選択するとカスタムドメインの設定画面に移行します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="336px" data-flex-grow="140" height="685" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/07.webp" srcset="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/07_hu_5616fba272d14413.webp 800w, https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/07.webp 959w" width="959"&gt;&lt;/p&gt;
&lt;p&gt;メニューからアクセスする場合は、&lt;strong&gt;Workers &amp;amp; Pages&lt;/strong&gt; の &lt;strong&gt;Custom domains&lt;/strong&gt; タブを選択します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="558px" data-flex-grow="232" height="459" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/08.webp" srcset="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/08_hu_fda31703fcc12606.webp 800w, https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/08.webp 1069w" width="1069"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Set up a custom domain&lt;/strong&gt; を選択します。&lt;br&gt;
続いて、適用したいドメインを入力し、&lt;strong&gt;Continue&lt;/strong&gt; をクリックします。&lt;br&gt;
すると、&lt;strong&gt;CNAME レコードが自動で追加されます&lt;/strong&gt;（手動編集は不要です）。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="502px" data-flex-grow="209" height="438" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/09.webp" srcset="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/09_hu_4303b6333e2844ea.webp 800w, https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/09.webp 917w" width="917"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Activate domain&lt;/strong&gt; をクリックすると設定完了です。&lt;br&gt;
TLS 証明書も Cloudflare 側で自動発行されます（数分待ちます）&lt;/p&gt;
&lt;h3 id="ssltls-モードの変更"&gt;&lt;a href="#ssltls-%e3%83%a2%e3%83%bc%e3%83%89%e3%81%ae%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;SSL/TLS モードの変更
&lt;/h3&gt;&lt;p&gt;SSL/TLS モードは &lt;strong&gt;Full (strict)&lt;/strong&gt; にしておきます。&lt;br&gt;
Cloudflare Pages の出口側は有効な証明書を持つので、Full (strict) でもエラーにはならず、Flexible のように HTTPS が中途半端な状態を避けられます。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SSL/TLS&lt;/strong&gt; の &lt;strong&gt;Overview&lt;/strong&gt; を選択し、SSL/TLS encryption の &lt;strong&gt;Configure&lt;/strong&gt; をクリックします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="558px" data-flex-grow="232" height="555" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/10.webp" srcset="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/10_hu_7d12418840684b2a.webp 800w, https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/10.webp 1292w" width="1292"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Full (Strict)&lt;/strong&gt; を選択して、&lt;strong&gt;Save&lt;/strong&gt; をクリックして完了です。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="254px" data-flex-grow="105" height="638" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/17/cloudflare-pages-gitlab/11.webp" width="676"&gt;&lt;/p&gt;
&lt;h2 id="気をつけること"&gt;&lt;a href="#%e6%b0%97%e3%82%92%e3%81%a4%e3%81%91%e3%82%8b%e3%81%93%e3%81%a8" class="header-anchor"&gt;&lt;/a&gt;気をつけること
&lt;/h2&gt;&lt;h3 id="node_version-の明示"&gt;&lt;a href="#node_version-%e3%81%ae%e6%98%8e%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;&lt;code&gt;NODE_VERSION&lt;/code&gt; の明示
&lt;/h3&gt;&lt;p&gt;Cloudflare Pages のデフォルト Node は古いことがあります。&lt;br&gt;
&lt;code&gt;package.json&lt;/code&gt; の &lt;code&gt;engines&lt;/code&gt; だけでは効かないので、&lt;strong&gt;ビルド設定の環境変数で明示します&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id="ビルド時間と無料枠"&gt;&lt;a href="#%e3%83%93%e3%83%ab%e3%83%89%e6%99%82%e9%96%93%e3%81%a8%e7%84%a1%e6%96%99%e6%9e%a0" class="header-anchor"&gt;&lt;/a&gt;ビルド時間と無料枠
&lt;/h3&gt;&lt;p&gt;無料枠は &lt;strong&gt;同時ビルド 1 並列・月 500 回まで&lt;/strong&gt;です。&lt;br&gt;
push のたびにビルドが走るので、頻繁な push を続けると上限に近づきます。CI ライクに何度も push しまくる運用には向きません。&lt;/p&gt;
&lt;p&gt;初回ビルドは &lt;code&gt;npm install&lt;/code&gt; がフレッシュで 5〜10 分かかることもあります。2 回目以降はキャッシュが効きます。&lt;/p&gt;
&lt;h3 id="プレビュー-url-の検索エンジン除外"&gt;&lt;a href="#%e3%83%97%e3%83%ac%e3%83%93%e3%83%a5%e3%83%bc-url-%e3%81%ae%e6%a4%9c%e7%b4%a2%e3%82%a8%e3%83%b3%e3%82%b8%e3%83%b3%e9%99%a4%e5%a4%96" class="header-anchor"&gt;&lt;/a&gt;プレビュー URL の検索エンジン除外
&lt;/h3&gt;&lt;p&gt;Cloudflare Pages は本番ドメイン以外（&lt;code&gt;&amp;lt;project&amp;gt;.pages.dev&lt;/code&gt; や &lt;code&gt;&amp;lt;branch&amp;gt;.&amp;lt;project&amp;gt;.pages.dev&lt;/code&gt;）にも &lt;strong&gt;自動で &lt;code&gt;X-Robots-Tag: noindex&lt;/code&gt; を付けます&lt;/strong&gt;。Google にプレビュー版がインデックスされる事故は基本的に起きません。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;&lt;a href="#%e3%81%be%e3%81%a8%e3%82%81" class="header-anchor"&gt;&lt;/a&gt;まとめ
&lt;/h2&gt;&lt;p&gt;すべて &lt;strong&gt;無料枠&lt;/strong&gt;で完結し、自前のサーバー運用はゼロです。&lt;br&gt;
GitLab に push して数分で本番反映される、最小構成になっています。&lt;/p&gt;
&lt;p&gt;GitLab Pages + Cloudflare プロキシでも同じことはできますが、TXT 検証や SSL モード調整など「2 サービスを連携させるための作業」が発生します。&lt;br&gt;
Cloudflare 内で完結させると、覚えることが 1 箇所にまとまって精神的に楽です。&lt;/p&gt;</description></item><item><title>Claude Code の認証情報とチャット履歴を devcontainer とホストで共有する</title><link>https://blog.ponkotools.com/posts/2026/05/13/claude-devcontainer-share/</link><pubDate>Wed, 13 May 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/05/13/claude-devcontainer-share/</guid><description>&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 24.04&lt;/li&gt;
&lt;li&gt;VSCode 1.119.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="きっかけ"&gt;&lt;a href="#%e3%81%8d%e3%81%a3%e3%81%8b%e3%81%91" class="header-anchor"&gt;&lt;/a&gt;きっかけ
&lt;/h2&gt;&lt;p&gt;devcontainer をリビルドするたびに Claude Code に再ログインするのが地味にストレスでした。さらに、ホスト側で進めていた会話の続きが devcontainer 側からは見えず、「あの修正の文脈どこに残してたっけ」となりがちでした。&lt;/p&gt;
&lt;h2 id="ゴール構成"&gt;&lt;a href="#%e3%82%b4%e3%83%bc%e3%83%ab%e6%a7%8b%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;ゴール構成
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ホスト・devcontainer のどちらで起動しても &lt;strong&gt;同じ認証情報&lt;/strong&gt; を使える&lt;/li&gt;
&lt;li&gt;ホストで途中まで進めた会話を devcontainer 側でも &lt;strong&gt;そのまま継続&lt;/strong&gt; できる&lt;/li&gt;
&lt;li&gt;リビルドしても再ログイン不要&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="claude-code-が何を見ているかを把握する"&gt;&lt;a href="#claude-code-%e3%81%8c%e4%bd%95%e3%82%92%e8%a6%8b%e3%81%a6%e3%81%84%e3%82%8b%e3%81%8b%e3%82%92%e6%8a%8a%e6%8f%a1%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;Claude Code が何を見ているかを把握する
&lt;/h2&gt;&lt;p&gt;設定の前に、Claude Code が以下の 2 つを参照していることを押さえておきます。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;種類&lt;/th&gt;
 &lt;th&gt;場所&lt;/th&gt;
 &lt;th&gt;役割&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;認証情報・設定&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;~/.claude.json&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;API キーなど&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;セッション履歴&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;~/.claude/projects/&amp;lt;エンコードしたパス&amp;gt;/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;プロジェクトごとの会話履歴&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;ポイントは、セッション履歴の格納先が &lt;strong&gt;プロジェクトの絶対パスをスラッシュ → ハイフンに変換した名前&lt;/strong&gt; になっていることです。&lt;/p&gt;
&lt;p&gt;例えばホスト側で &lt;code&gt;/home/&amp;lt;username&amp;gt;/&amp;lt;project_name&amp;gt;&lt;/code&gt; を開いていた場合は、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~/.claude/projects/-home-&amp;lt;username&amp;gt;-&amp;lt;project_name&amp;gt;/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;の下に履歴が溜まります。&lt;/p&gt;
&lt;p&gt;つまり、履歴を共有したいなら &lt;strong&gt;ホストとコンテナで「ワークスペースの絶対パス」を一致させる必要がある&lt;/strong&gt; ということです。&lt;code&gt;~/.claude&lt;/code&gt; だけ bind mount しても、コンテナ側のワークスペースパスがホストと違えば別フォルダ扱いになり、履歴は共有されません。&lt;/p&gt;
&lt;h2 id="設定する-2-つのマウント"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a%e3%81%99%e3%82%8b-2-%e3%81%a4%e3%81%ae%e3%83%9e%e3%82%a6%e3%83%b3%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;設定する 2 つのマウント
&lt;/h2&gt;&lt;p&gt;必要なマウントは性質の違う 2 種類になります。&lt;/p&gt;
&lt;h3 id="1-claude--claudejson-のマウント--コンテナ側ユーザーの-home-に合わせる"&gt;&lt;a href="#1-claude--claudejson-%e3%81%ae%e3%83%9e%e3%82%a6%e3%83%b3%e3%83%88--%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e5%81%b4%e3%83%a6%e3%83%bc%e3%82%b6%e3%83%bc%e3%81%ae-home-%e3%81%ab%e5%90%88%e3%82%8f%e3%81%9b%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;1. &lt;code&gt;.claude&lt;/code&gt; / &lt;code&gt;.claude.json&lt;/code&gt; のマウント (= コンテナ側ユーザーの home に合わせる)
&lt;/h3&gt;&lt;p&gt;Claude Code は &lt;strong&gt;そのプロセスの &lt;code&gt;$HOME/.claude&lt;/code&gt;&lt;/strong&gt; を読みに行きます。devcontainer のデフォルトユーザーは &lt;code&gt;vscode&lt;/code&gt; なので、&lt;code&gt;~&lt;/code&gt; は &lt;code&gt;/home/vscode&lt;/code&gt; です。したがってターゲットも &lt;code&gt;/home/vscode/.claude&lt;/code&gt; にします。&lt;/p&gt;
&lt;h3 id="2-ワークスペースのマウント--ホスト側の絶対パスに合わせる"&gt;&lt;a href="#2-%e3%83%af%e3%83%bc%e3%82%af%e3%82%b9%e3%83%9a%e3%83%bc%e3%82%b9%e3%81%ae%e3%83%9e%e3%82%a6%e3%83%b3%e3%83%88--%e3%83%9b%e3%82%b9%e3%83%88%e5%81%b4%e3%81%ae%e7%b5%b6%e5%af%be%e3%83%91%e3%82%b9%e3%81%ab%e5%90%88%e3%82%8f%e3%81%9b%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;2. ワークスペースのマウント (= ホスト側の絶対パスに合わせる)
&lt;/h3&gt;&lt;p&gt;こちらはセッション履歴のキーになる「プロジェクトの絶対パス」を一致させるのが目的なので、ターゲットを &lt;strong&gt;ホスト側と同じパス&lt;/strong&gt; にします。ホストの &lt;code&gt;~/&amp;lt;project_name&amp;gt;&lt;/code&gt; を開いているなら、コンテナ内でも &lt;code&gt;/home/&amp;lt;username&amp;gt;/&amp;lt;project_name&amp;gt;&lt;/code&gt; にマウントするということです。&lt;/p&gt;
&lt;p&gt;ターゲットの基準が違う (ユーザー基準 vs ホスト基準) のがややこしい部分なので、表にしておきます。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;マウント&lt;/th&gt;
 &lt;th&gt;ターゲット&lt;/th&gt;
 &lt;th&gt;基準&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;~/.claude&lt;/code&gt; &lt;code&gt;~/.claude.json&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/home/vscode/.claude&lt;/code&gt; &lt;code&gt;/home/vscode/.claude.json&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;コンテナ内ユーザー&lt;/strong&gt; の home&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ワークスペース&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/home/&amp;lt;username&amp;gt;/&amp;lt;project_name&amp;gt;&lt;/code&gt; 等&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;ホスト側&lt;/strong&gt; の絶対パス&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="devcontainerjson-の例"&gt;&lt;a href="#devcontainerjson-%e3%81%ae%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;devcontainer.json の例
&lt;/h2&gt;&lt;p&gt;上記を踏まえた &lt;code&gt;.devcontainer/devcontainer.json&lt;/code&gt; の抜粋です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-jsonc" data-lang="jsonc"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;my-devcontainer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;build&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;dockerfile&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Dockerfile&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// ホストの $HOME を build arg として Dockerfile に渡す
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// (workspace の親ディレクトリを事前に作るために使う。後述)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;WORKSPACE_PARENT&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;${localEnv:HOME}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// ワークスペースのマウント先をホスト側の絶対パスと一致させる。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// フォルダ名は localWorkspaceFolderBasename で動的解決するので、
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// ホスト側を rename しても devcontainer.json の編集は不要。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;workspaceMount&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;source=${localWorkspaceFolder},target=${localEnv:HOME}/${localWorkspaceFolderBasename},type=bind,consistency=cached&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;workspaceFolder&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;${localEnv:HOME}/${localWorkspaceFolderBasename}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mounts&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// .claude / .claude.json はコンテナ内ユーザー (vscode) の home にマウント
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;source=${localEnv:HOME}/.claude,target=/home/vscode/.claude,type=bind,consistency=cached&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;source=${localEnv:HOME}/.claude.json,target=/home/vscode/.claude.json,type=bind,consistency=cached&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;remoteUser&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;vscode&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;${localEnv:HOME}&lt;/code&gt; は &lt;strong&gt;ホスト側&lt;/strong&gt; の &lt;code&gt;$HOME&lt;/code&gt; (例: &lt;code&gt;/home/&amp;lt;username&amp;gt;&lt;/code&gt;)、&lt;code&gt;${localWorkspaceFolderBasename}&lt;/code&gt; は VSCode が開いているフォルダ名 (例: &lt;code&gt;&amp;lt;project_name&amp;gt;&lt;/code&gt;) に展開されます。両者を組み合わせることで、ホストで開いているパスと完全に同じ絶対パスをコンテナ内に作れます。&lt;/p&gt;
&lt;h2 id="dockerfile-側で親ディレクトリを用意しておく"&gt;&lt;a href="#dockerfile-%e5%81%b4%e3%81%a7%e8%a6%aa%e3%83%87%e3%82%a3%e3%83%ac%e3%82%af%e3%83%88%e3%83%aa%e3%82%92%e7%94%a8%e6%84%8f%e3%81%97%e3%81%a6%e3%81%8a%e3%81%8f" class="header-anchor"&gt;&lt;/a&gt;Dockerfile 側で親ディレクトリを用意しておく
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;workspaceFolder&lt;/code&gt; に指定したパスの &lt;strong&gt;親ディレクトリ&lt;/strong&gt; がコンテナ内に存在しないと、Dev Containers の起動チェックで「ワークスペースが存在しません」とエラーになります。bind mount はマウント時にターゲットを作ってくれますが、Dev Containers のチェックがそれより先に走るためです。&lt;/p&gt;
&lt;p&gt;そこで Dockerfile 側で親ディレクトリだけ先に作っておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/devcontainers/base:bookworm&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# devcontainer.json の workspaceFolder (= ホストの $HOME/&amp;lt;フォルダ名&amp;gt;) と&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 同じ絶対パスをコンテナ内に用意しておく。&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ARG&lt;/span&gt; &lt;span class="nv"&gt;WORKSPACE_PARENT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/vscode&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; mkdir -p &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;WORKSPACE_PARENT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ARG のデフォルト値を &lt;code&gt;/home/vscode&lt;/code&gt; にしておけば、build arg を渡し忘れても既存ユーザーのホームが使われるだけで build が壊れることはありません。&lt;/p&gt;
&lt;h2 id="ユーザーは-vscode-のままでよい"&gt;&lt;a href="#%e3%83%a6%e3%83%bc%e3%82%b6%e3%83%bc%e3%81%af-vscode-%e3%81%ae%e3%81%be%e3%81%be%e3%81%a7%e3%82%88%e3%81%84" class="header-anchor"&gt;&lt;/a&gt;ユーザーは vscode のままでよい
&lt;/h2&gt;&lt;p&gt;「ワークスペースが &lt;code&gt;/home/&amp;lt;username&amp;gt;/&amp;lt;project_name&amp;gt;&lt;/code&gt; なのに &lt;code&gt;whoami&lt;/code&gt; すると &lt;code&gt;vscode&lt;/code&gt; になっている」というアンバランスさが気になるかもしれませんが、機能上は問題ありません。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;devcontainers/base の &lt;code&gt;vscode&lt;/code&gt; ユーザーは UID 1000&lt;/li&gt;
&lt;li&gt;ホスト側の Linux ユーザーも通常 UID 1000&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;UID が一致していれば bind mount したファイルにそのまま読み書きできるためです。&lt;code&gt;vscode&lt;/code&gt; ユーザーが自分の home (&lt;code&gt;/home/vscode/&lt;/code&gt;) 以外の場所で作業すること自体は何も問題を起こしません。&lt;/p&gt;
&lt;p&gt;ユーザー名まで揃えようとすると base image の改造が必要になり、devcontainer features が前提にしている &lt;code&gt;vscode&lt;/code&gt; ユーザーが消えて壊れがちです。&lt;strong&gt;ホストと揃えるのは「絶対パス」だけで十分&lt;/strong&gt; と割り切るのが楽です。&lt;/p&gt;
&lt;h2 id="注意点"&gt;&lt;a href="#%e6%b3%a8%e6%84%8f%e7%82%b9" class="header-anchor"&gt;&lt;/a&gt;注意点
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ホスト側に &lt;code&gt;~/.claude&lt;/code&gt; と &lt;code&gt;~/.claude.json&lt;/code&gt; が存在している必要があります&lt;/strong&gt;。なければ bind mount に失敗します。ホスト側でも一度 Claude Code を起動して認証を済ませておくのが手っ取り早いです。&lt;/li&gt;
&lt;li&gt;セッション履歴を &lt;strong&gt;ホストと同時に書き込まない&lt;/strong&gt; よう注意してください。両方から同じプロジェクトを同時に触ると、ファイルロック等の衝突で履歴が壊れることがあります。基本「どちらか一方で作業する」運用が安全です。&lt;/li&gt;
&lt;li&gt;設定変更後は VSCode の &lt;strong&gt;Dev Containers: Rebuild Container&lt;/strong&gt; でリビルドしないと反映されません。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="まとめ"&gt;&lt;a href="#%e3%81%be%e3%81%a8%e3%82%81" class="header-anchor"&gt;&lt;/a&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Claude Code のセッション履歴は &lt;strong&gt;プロジェクトの絶対パスをキー&lt;/strong&gt; にして格納される。&lt;/li&gt;
&lt;li&gt;なので「ホストとセッション共有したい」ならコンテナ内のワークスペースパスをホスト側と完全一致させる必要がある。&lt;/li&gt;
&lt;li&gt;マウント先は 2 系統で基準が違う:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.claude&lt;/code&gt; / &lt;code&gt;.claude.json&lt;/code&gt; は &lt;strong&gt;コンテナ内ユーザーの home&lt;/strong&gt; に合わせる&lt;/li&gt;
&lt;li&gt;ワークスペースは &lt;strong&gt;ホスト側の絶対パス&lt;/strong&gt; に合わせる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ワークスペースの親ディレクトリは Dockerfile 側で &lt;code&gt;mkdir -p&lt;/code&gt; しておく必要がある。&lt;/li&gt;
&lt;li&gt;フォルダ名は &lt;code&gt;${localWorkspaceFolderBasename}&lt;/code&gt; で動的解決すれば、rename にも追従する。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Cloudflare で取得した独自ドメインを GitLab Pages に設定する方法</title><link>https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/</link><pubDate>Tue, 12 May 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/</guid><description>&lt;h2 id="全体の流れ"&gt;&lt;a href="#%e5%85%a8%e4%bd%93%e3%81%ae%e6%b5%81%e3%82%8c" class="header-anchor"&gt;&lt;/a&gt;全体の流れ
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;GitLab側&lt;/strong&gt;: カスタムドメイン登録と検証コードの取得&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitLab側&lt;/strong&gt;: Pagesの公開範囲（Visibility）の設定&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloudflare側&lt;/strong&gt;: DNSレコード（CNAME/TXT）の設定&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最終確認&lt;/strong&gt;: SSL証明書の発行とプロキシの有効化&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="1-gitlab側でカスタムドメインを追加する"&gt;&lt;a href="#1-gitlab%e5%81%b4%e3%81%a7%e3%82%ab%e3%82%b9%e3%82%bf%e3%83%a0%e3%83%89%e3%83%a1%e3%82%a4%e3%83%b3%e3%82%92%e8%bf%bd%e5%8a%a0%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;1. GitLab側でカスタムドメインを追加する
&lt;/h2&gt;&lt;p&gt;まず、GitLabに「このドメインを使います」と伝えて、検証用のコードを発行します。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;プロジェクトの左メニュー &lt;strong&gt;[Deploy] &amp;gt; [Pages]&lt;/strong&gt; を開きます。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Domains &amp;amp; settings&lt;/strong&gt; のタブを選択し、&lt;strong&gt;[Add Domain]&lt;/strong&gt; をクリックします。&lt;br&gt;
&lt;img class="gallery-image" data-flex-basis="551px" data-flex-grow="229" height="496" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/01.webp" srcset="https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/01_hu_da00e0f781f44ee3.webp 800w, https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/01.webp 1139w" width="1139"&gt;&lt;/li&gt;
&lt;li&gt;使用したいドメイン（例: &lt;code&gt;blog.example.com&lt;/code&gt;）を入力し、&lt;strong&gt;[Create new domain]&lt;/strong&gt; をクリックします。&lt;br&gt;
&lt;img class="gallery-image" data-flex-basis="472px" data-flex-grow="196" height="445" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/02.webp" srcset="https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/02_hu_719ccfceb99c9603.webp 800w, https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/02.webp 876w" width="876"&gt;&lt;/li&gt;
&lt;li&gt;表示された画面から以下の2点をメモします。
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TXTレコードの値&lt;/strong&gt;: &lt;code&gt;gitlab-pages-verification-code=...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CNAMEのターゲット&lt;/strong&gt;: &lt;code&gt;username-12345.gitlab.io&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="自分の名前空間targetを確認する方法"&gt;&lt;a href="#%e8%87%aa%e5%88%86%e3%81%ae%e5%90%8d%e5%89%8d%e7%a9%ba%e9%96%93target%e3%82%92%e7%a2%ba%e8%aa%8d%e3%81%99%e3%82%8b%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;自分の「名前空間（Target）」を確認する方法
&lt;/h3&gt;&lt;p&gt;GitLab PagesのデフォルトURLを確認してください。
例：&lt;code&gt;https://username-12345.gitlab.io/my-project&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;この場合、Cloudflare側で指定するターゲットは &lt;strong&gt;&lt;code&gt;username-12345.gitlab.io&lt;/code&gt;&lt;/strong&gt; です。
&lt;code&gt;.gitlab.io&lt;/code&gt; の直前まで（スラッシュより前のホスト部分）が、あなたの「名前空間（Namespace）」となります。&lt;/p&gt;
&lt;h2 id="2-プロジェクトはprivateのままpagesだけを公開する"&gt;&lt;a href="#2-%e3%83%97%e3%83%ad%e3%82%b8%e3%82%a7%e3%82%af%e3%83%88%e3%81%afprivate%e3%81%ae%e3%81%be%e3%81%bepages%e3%81%a0%e3%81%91%e3%82%92%e5%85%ac%e9%96%8b%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;2. プロジェクトはPrivateのまま、Pagesだけを公開する
&lt;/h2&gt;&lt;p&gt;「ソースコードは見せたくないが、ブログとして誰でも見れるようにしたい」場合は、以下の設定が必須です。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;[Settings] &amp;gt; [General]&lt;/strong&gt; を開きます。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;[Visibility, project features and permissions]&lt;/strong&gt; セクションを展開します。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Project visibility&lt;/strong&gt; は &lt;strong&gt;[Private]&lt;/strong&gt; のままにします。&lt;/li&gt;
&lt;li&gt;下の方にある &lt;strong&gt;[Pages]&lt;/strong&gt; の権限設定を &lt;strong&gt;[Everyone]&lt;/strong&gt; に変更します。
&lt;ul&gt;
&lt;li&gt;※ここが &lt;code&gt;Only Project Members&lt;/code&gt; だと、独自ドメインにアクセスしてもGitLabのログイン画面が出てしまいます。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;[Save changes]&lt;/strong&gt; で保存します。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="3-cloudflare側でdnsレコードを設定する"&gt;&lt;a href="#3-cloudflare%e5%81%b4%e3%81%a7dns%e3%83%ac%e3%82%b3%e3%83%bc%e3%83%89%e3%82%92%e8%a8%ad%e5%ae%9a%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;3. Cloudflare側でDNSレコードを設定する
&lt;/h2&gt;&lt;p&gt;Cloudflareの管理画面の左メニューから &lt;strong&gt;[Domains] &amp;gt; [Overview]&lt;/strong&gt; を開き、該当のドメインをクリックします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="1048px" data-flex-grow="436" height="357" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/03.webp" srcset="https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/03_hu_fa7e6c6c7efaf40f.webp 800w, https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/03.webp 1559w" width="1559"&gt;&lt;/p&gt;
&lt;p&gt;さらに左メニューから &lt;strong&gt;[DNS] &amp;gt; [Records]&lt;/strong&gt; を開き、&lt;strong&gt;Add record&lt;/strong&gt; をクリックして、以下の2つのレコードを追加します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="555px" data-flex-grow="231" height="656" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/04.webp" srcset="https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/04_hu_cd257f623ecf097.webp 800w, https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/04.webp 1518w" width="1518"&gt;&lt;/p&gt;
&lt;h3 id="-cnameレコード接続用"&gt;&lt;a href="#-cname%e3%83%ac%e3%82%b3%e3%83%bc%e3%83%89%e6%8e%a5%e7%b6%9a%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;① CNAMEレコード（接続用）
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;項目&lt;/th&gt;
 &lt;th style="text-align: left"&gt;設定値の例&lt;/th&gt;
 &lt;th style="text-align: left"&gt;補足&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;CNAME&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;blog&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;サブドメイン部分のみ入力&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Target&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;username-12345.gitlab.io&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;先ほど確認したGitLabのホスト名&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Proxy status&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;DNS only (灰色雲)&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;SSL発行をスムーズにするため最初は必ず「灰色」にする&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="-txtレコードドメイン所有確認用"&gt;&lt;a href="#-txt%e3%83%ac%e3%82%b3%e3%83%bc%e3%83%89%e3%83%89%e3%83%a1%e3%82%a4%e3%83%b3%e6%89%80%e6%9c%89%e7%a2%ba%e8%aa%8d%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;② TXTレコード（ドメイン所有確認用）
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;項目&lt;/th&gt;
 &lt;th style="text-align: left"&gt;設定値の例&lt;/th&gt;
 &lt;th style="text-align: left"&gt;補足&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;TXT&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;_gitlab-pages-verification-code.blog&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;_gitlab-pages-verification-code.&lt;/code&gt; の後にサブドメイン名を付ける&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Content&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;gitlab-pages-verification-code=...&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;GitLabからコピーした検証コード&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="4-仕上げ検証とプロキシ有効化"&gt;&lt;a href="#4-%e4%bb%95%e4%b8%8a%e3%81%92%e6%a4%9c%e8%a8%bc%e3%81%a8%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e6%9c%89%e5%8a%b9%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;4. 仕上げ：検証とプロキシ有効化
&lt;/h2&gt;&lt;h3 id="-gitlabで検証する"&gt;&lt;a href="#-gitlab%e3%81%a7%e6%a4%9c%e8%a8%bc%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;① GitLabで検証する
&lt;/h3&gt;&lt;p&gt;DNS設定後、GitLabのPages設定画面で &lt;strong&gt;[Verify]&lt;/strong&gt;（更新マーク）ボタンを押します。「Verified」になれば成功です。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="451px" data-flex-grow="188" height="470" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/05.webp" srcset="https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/05_hu_e848a83d0f43a8b7.webp 800w, https://blog.ponkotools.com/posts/2026/05/12/cloudflare-gitlab/05.webp 884w" width="884"&gt;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;⚠️ &lt;strong&gt;すぐに認証されない場合があります。&lt;/strong&gt; Cloudflare管理ドメインはDNSのTTLが短いため反映は比較的早いですが、DNSの浸透には最大48時間かかることがあります。Verifyが通らない場合は時間をおいて再試行してください。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h3 id="-ssl証明書の発行を待つ"&gt;&lt;a href="#-ssl%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%ae%e7%99%ba%e8%a1%8c%e3%82%92%e5%be%85%e3%81%a4" class="header-anchor"&gt;&lt;/a&gt;② SSL証明書の発行を待つ
&lt;/h3&gt;&lt;p&gt;検証完了後、数分〜30分ほどでLet&amp;rsquo;s Encryptの証明書が自動発行され、&lt;code&gt;https://&lt;/code&gt; でアクセスできるようになります。&lt;/p&gt;
&lt;h3 id="-cloudflareのプロキシをonにする"&gt;&lt;a href="#-cloudflare%e3%81%ae%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e3%82%92on%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;③ CloudflareのプロキシをONにする
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;https://&lt;/code&gt; で正常に表示されたことを確認してから、CloudflareのDNSレコードを &lt;strong&gt;[Proxied（オレンジ雲）]&lt;/strong&gt; に切り替えます。&lt;/p&gt;
&lt;h4 id="プロキシを-on-にするメリット"&gt;&lt;a href="#%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e3%82%92-on-%e3%81%ab%e3%81%99%e3%82%8b%e3%83%a1%e3%83%aa%e3%83%83%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;プロキシを ON にするメリット
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CDNによる高速化&lt;/strong&gt;: 画像やJSがキャッシュされ、表示速度が向上します。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;セキュリティ強化&lt;/strong&gt;: DDoS保護やWAFが利用可能になります。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;アクセス解析&lt;/strong&gt;: Cloudflare側でトラフィックやアクセス地域を確認できます。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="-cloudflareのssltls設定を変更する"&gt;&lt;a href="#-cloudflare%e3%81%aessltls%e8%a8%ad%e5%ae%9a%e3%82%92%e5%a4%89%e6%9b%b4%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;④ CloudflareのSSL/TLS設定を変更する
&lt;/h3&gt;&lt;p&gt;プロキシを有効にしたら、Cloudflareの &lt;strong&gt;[SSL/TLS] &amp;gt; [Overview]&lt;/strong&gt; を開き、暗号化モードを確認します。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;モード&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;th style="text-align: left"&gt;推奨&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;Full&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;GitLab側の証明書を検証せず暗号化&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;初心者・通常利用向け&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;Full (strict)&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;GitLab側にLet&amp;rsquo;s Encryptなど信頼されたCA発行の証明書が必要&lt;/td&gt;
 &lt;td style="text-align: left"&gt;SSL発行が正常に完了していれば利用可&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;

 &lt;blockquote&gt;
 &lt;p&gt;⚠️ &lt;code&gt;Full (strict)&lt;/code&gt; はSSL証明書が有効な状態でのみ機能します。証明書の発行前や更新タイミングで一時的にエラーになるリスクがあるため、迷ったら &lt;strong&gt;&lt;code&gt;Full&lt;/code&gt;&lt;/strong&gt; を選択してください。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="5-運用上の注意キャッシュの扱い"&gt;&lt;a href="#5-%e9%81%8b%e7%94%a8%e4%b8%8a%e3%81%ae%e6%b3%a8%e6%84%8f%e3%82%ad%e3%83%a3%e3%83%83%e3%82%b7%e3%83%a5%e3%81%ae%e6%89%b1%e3%81%84" class="header-anchor"&gt;&lt;/a&gt;5. 運用上の注意：キャッシュの扱い
&lt;/h2&gt;&lt;p&gt;Cloudflareのプロキシを有効にすると、CSSや画像などの静的ファイルがキャッシュされます。
&lt;strong&gt;サイトを更新しても古いコンテンツが表示される場合&lt;/strong&gt;は、Cloudflareのキャッシュをクリアしてください。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;手動でキャッシュをクリアする方法:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Cloudflareダッシュボードの &lt;strong&gt;[Caching] &amp;gt; [Configuration]&lt;/strong&gt; を開く&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;[Purge Cache]&lt;/strong&gt; &amp;gt; &lt;strong&gt;[Purge Everything]&lt;/strong&gt;（または特定URLを指定）を実行する&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="まとめ"&gt;&lt;a href="#%e3%81%be%e3%81%a8%e3%82%81" class="header-anchor"&gt;&lt;/a&gt;まとめ
&lt;/h2&gt;&lt;p&gt;GitLab Pagesを独自ドメインで運用する主なポイントは以下の3点です。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;正しいCNAMEターゲットを設定する&lt;/strong&gt; — GitLabのPages URLから実際のホスト名を確認して使う&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PagesのVisibilityを「Everyone」にする&lt;/strong&gt; — Privateプロジェクトでも公開アクセスを許可する&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SSL発行前はプロキシを灰色に保つ&lt;/strong&gt; — 証明書が発行されてからオレンジ雲に切り替える&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>GitHub CLI (gh auth login) で Git の HTTPS 認証を安全にする</title><link>https://blog.ponkotools.com/posts/2026/05/11/github-cli-auth/</link><pubDate>Mon, 11 May 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/05/11/github-cli-auth/</guid><description>&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 24.04&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="きっかけ"&gt;&lt;a href="#%e3%81%8d%e3%81%a3%e3%81%8b%e3%81%91" class="header-anchor"&gt;&lt;/a&gt;きっかけ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;git remote -v&lt;/code&gt; を眺めていたら、Personal Access Token (PAT) が remote URL に丸ごと埋め込まれている状態になっていました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;origin https://ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxx@github.com/USER/REPO.git (fetch)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;origin https://ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxx@github.com/USER/REPO.git (push)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;.git/config&lt;/code&gt; はリポジトリに含まれないため「push しても外には出ない」ものの、ローカルで露出する経路は意外と多くあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;シェル履歴 (&lt;code&gt;~/.bash_history&lt;/code&gt; &lt;code&gt;~/.zsh_history&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;エディタや CI のログ、画面共有・スクリーンショット&lt;/li&gt;
&lt;li&gt;うっかり配布した dotfiles リポジトリ&lt;/li&gt;
&lt;li&gt;マルウェアやリモートアクセスで &lt;code&gt;.git/config&lt;/code&gt; が読まれる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;しかも classic PAT はスコープが粗く、&lt;code&gt;repo&lt;/code&gt; 権限があれば private リポジトリ全体の閲覧・書き換え、強制 push による履歴破壊、GitHub Actions secrets の窃取まで可能になります。攻撃者は奪った瞬間には何もせず静かに watch することもできるため、「使われた形跡がない」では安心できません。&lt;/p&gt;
&lt;p&gt;これを機に、PAT を URL に埋めず GitHub CLI (&lt;code&gt;gh&lt;/code&gt;) の credential helper に任せる構成に切り替えました。&lt;/p&gt;
&lt;h2 id="ゴール構成"&gt;&lt;a href="#%e3%82%b4%e3%83%bc%e3%83%ab%e6%a7%8b%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;ゴール構成
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;remote URL は素の &lt;code&gt;https://github.com/USER/REPO.git&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;認証は &lt;code&gt;gh&lt;/code&gt; が credential helper として処理 (トークンは OS のセキュアストア管理)&lt;/li&gt;
&lt;li&gt;devcontainer を作り直しても再ログイン不要&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="手順"&gt;&lt;a href="#%e6%89%8b%e9%a0%86" class="header-anchor"&gt;&lt;/a&gt;手順
&lt;/h2&gt;&lt;h3 id="1-露出したトークンを-revoke-最優先"&gt;&lt;a href="#1-%e9%9c%b2%e5%87%ba%e3%81%97%e3%81%9f%e3%83%88%e3%83%bc%e3%82%af%e3%83%b3%e3%82%92-revoke-%e6%9c%80%e5%84%aa%e5%85%88" class="header-anchor"&gt;&lt;/a&gt;1. 露出したトークンを revoke (最優先)
&lt;/h3&gt;&lt;p&gt;remote URL を書き換える前に、まず GitHub 側でトークンを無効化します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;classic PAT: &lt;a class="link" href="https://github.com/settings/tokens" target="_blank" rel="noopener"
 &gt;https://github.com/settings/tokens&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;fine-grained PAT: &lt;a class="link" href="https://github.com/settings/personal-access-tokens" target="_blank" rel="noopener"
 &gt;https://github.com/settings/personal-access-tokens&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;該当トークンを Delete した瞬間に無効になります。順序として &lt;strong&gt;これを先にやる&lt;/strong&gt; ことが大切です。後の手順を待っている間に古いトークンが他経路で使われるリスクを断ちます。&lt;/p&gt;
&lt;h3 id="2-gh-をインストール"&gt;&lt;a href="#2-gh-%e3%82%92%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;2. &lt;code&gt;gh&lt;/code&gt; をインストール
&lt;/h3&gt;&lt;p&gt;devcontainer 環境なら &lt;code&gt;ghcr.io/devcontainers/features/github-cli&lt;/code&gt; feature で &lt;code&gt;gh&lt;/code&gt; がすでに入っています。&lt;/p&gt;
&lt;p&gt;ホスト (Ubuntu 24.04) に入れる場合は、以下の記事を参考にしてください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.ponkotools.com/posts/2026/05/09/github-cli/" &gt;GitHub CLI (gh) のインストールと基本的な使い方&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-gh-auth-login-で認証"&gt;&lt;a href="#3-gh-auth-login-%e3%81%a7%e8%aa%8d%e8%a8%bc" class="header-anchor"&gt;&lt;/a&gt;3. &lt;code&gt;gh auth login&lt;/code&gt; で認証
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh auth login
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;対話で以下のように選びます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Where do you use GitHub? GitHub.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? What is your preferred protocol for Git operations? HTTPS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Authenticate Git with your GitHub credentials? Yes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? How would you like to authenticate GitHub CLI? Login with a web browser
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Authenticate Git with your GitHub credentials? → Yes&lt;/code&gt; が肝で、これが &lt;code&gt;git config --global credential.helper&lt;/code&gt; を &lt;code&gt;gh&lt;/code&gt; 経由に書き換えてくれます。以後 &lt;code&gt;git push&lt;/code&gt; のたびに &lt;code&gt;gh&lt;/code&gt; が裏でトークンを取り出して認証してくれます。&lt;/p&gt;
&lt;p&gt;devcontainer のようなヘッドレス環境ではブラウザは自動で開きません。表示される 8 桁のワンタイムコードをコピーし、ホスト側のブラウザで &lt;a class="link" href="https://github.com/login/device" target="_blank" rel="noopener"
 &gt;https://github.com/login/device&lt;/a&gt; に貼って承認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✓ Authentication complete.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✓ Logged in as USER
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-remote-url-からトークンを除去"&gt;&lt;a href="#4-remote-url-%e3%81%8b%e3%82%89%e3%83%88%e3%83%bc%e3%82%af%e3%83%b3%e3%82%92%e9%99%a4%e5%8e%bb" class="header-anchor"&gt;&lt;/a&gt;4. remote URL からトークンを除去
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git remote set-url origin https://github.com/USER/REPO.git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git remote -v
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;トークン部分が消えていれば OK です。&lt;code&gt;git fetch origin&lt;/code&gt; がパスワードを聞かれずに通れば認証は機能しています。&lt;/p&gt;
&lt;h3 id="5-シェル履歴の残骸を確認"&gt;&lt;a href="#5-%e3%82%b7%e3%82%a7%e3%83%ab%e5%b1%a5%e6%ad%b4%e3%81%ae%e6%ae%8b%e9%aa%b8%e3%82%92%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;5. シェル履歴の残骸を確認
&lt;/h3&gt;&lt;p&gt;revoke 済みでも、ローカル履歴に残ったトークン文字列は気持ちが悪いものです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -rn &lt;span class="s1"&gt;&amp;#39;ghp_&amp;#39;&lt;/span&gt; ~/.bash_history ~/.zsh_history 2&amp;gt;/dev/null
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ヒットしたら該当行を削除します (&lt;code&gt;history -d &amp;lt;行番号&amp;gt;&lt;/code&gt; でメモリ上を消した後、ファイルも編集しておきます)。&lt;/p&gt;
&lt;h2 id="devcontainer-での認証共有"&gt;&lt;a href="#devcontainer-%e3%81%a7%e3%81%ae%e8%aa%8d%e8%a8%bc%e5%85%b1%e6%9c%89" class="header-anchor"&gt;&lt;/a&gt;devcontainer での認証共有
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;gh&lt;/code&gt; の認証情報は &lt;code&gt;~/.config/gh/hosts.yml&lt;/code&gt; (と OS のセキュアストア) に保存されます。devcontainer をリビルドすると &lt;code&gt;~/.config/gh&lt;/code&gt; が消えて再ログインが必要になるため、ホストの設定を bind mount で共有します。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.devcontainer/devcontainer.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-jsonc" data-lang="jsonc"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;mounts&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;source=${localEnv:HOME}/.claude,target=/home/vscode/.claude,type=bind,consistency=cached&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;source=${localEnv:HOME}/.claude.json,target=/home/vscode/.claude.json,type=bind,consistency=cached&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;source=${localEnv:HOME}/.config/gh,target=/home/vscode/.config/gh,type=bind,consistency=cached&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;前提として &lt;strong&gt;ホスト側に &lt;code&gt;~/.config/gh&lt;/code&gt; ディレクトリが存在している必要があります&lt;/strong&gt; (なければ bind mount に失敗します)。ホストにも &lt;code&gt;gh&lt;/code&gt; を入れて &lt;code&gt;gh auth login&lt;/code&gt; 済みにしておくのが一番シンプルです。事情があってホスト側で &lt;code&gt;gh&lt;/code&gt; を使わない場合でも、空ディレクトリだけ作っておけばマウント自体は通ります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p ~/.config/gh &lt;span class="c1"&gt;# ホスト側で実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;設定変更後は VSCode の &lt;strong&gt;Dev Containers: Rebuild Container&lt;/strong&gt; でリビルドすると反映されます。&lt;/p&gt;
&lt;h2 id="補足-ssh-鍵にしないのか"&gt;&lt;a href="#%e8%a3%9c%e8%b6%b3-ssh-%e9%8d%b5%e3%81%ab%e3%81%97%e3%81%aa%e3%81%84%e3%81%ae%e3%81%8b" class="header-anchor"&gt;&lt;/a&gt;補足: SSH 鍵にしないのか
&lt;/h2&gt;&lt;p&gt;SSH 鍵認証もアリですが、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;鍵ファイル自体の管理 (&lt;code&gt;~/.ssh&lt;/code&gt; のパーミッション、複数マシン間の同期) が発生します&lt;/li&gt;
&lt;li&gt;GitHub Actions など他用途で &lt;code&gt;gh&lt;/code&gt; をどのみち使うことが多いです&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そのため、個人開発の HTTPS なら &lt;code&gt;gh auth login&lt;/code&gt; ひとつに寄せた方がメンテが楽だと感じています。複数アカウントの切替も &lt;code&gt;gh auth switch&lt;/code&gt; で済むのが良いところです。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;&lt;a href="#%e3%81%be%e3%81%a8%e3%82%81" class="header-anchor"&gt;&lt;/a&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;PAT を URL に埋めるのは「公開リポジトリに含まれない」だけでローカル経路の露出リスクは大きいです。露出に気付いた時点で revoke が最優先となります。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gh auth login&lt;/code&gt; で credential helper を任せれば URL からトークンを排除でき、トークンは OS のセキュアストアに隔離されます。&lt;/li&gt;
&lt;li&gt;devcontainer ではホストの &lt;code&gt;~/.config/gh&lt;/code&gt; を bind mount しておくと、リビルドのたびに再ログインしなくて済みます。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>ターミナルから GitLab を操る：公式 CLI「glab」導入・活用ガイド</title><link>https://blog.ponkotools.com/posts/2026/05/10/glab/</link><pubDate>Sun, 10 May 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/05/10/glab/</guid><description>&lt;p&gt;ブラウザを開かずに Issue を確認したり、MR（マージリクエスト）を作成したり、CI/CD パイプラインの状況を監視したりできるため、エンジニアの生産性を大きく向上させてくれます。&lt;/p&gt;
&lt;h2 id="1-インストール方法"&gt;&lt;a href="#1-%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;1. インストール方法
&lt;/h2&gt;&lt;p&gt;devcontainer を使っていない場合は、ホスト側に &lt;code&gt;glab&lt;/code&gt; をインストールして使います。devcontainer を使う場合は、コンテナイメージに &lt;code&gt;glab&lt;/code&gt; をインストールしておくか、devcontainer の &lt;code&gt;Dockerfile&lt;/code&gt; / &lt;code&gt;devcontainer.json&lt;/code&gt; で導入しておきます。&lt;/p&gt;
&lt;p&gt;一般的な手順としては、&lt;code&gt;Dockerfile&lt;/code&gt; に &lt;code&gt;curl&lt;/code&gt; で &lt;code&gt;glab&lt;/code&gt; の公式パッケージを取得して &lt;code&gt;apt install&lt;/code&gt; するか、&lt;code&gt;apt&lt;/code&gt; リポジトリからインストールする形です。コンテナ内で &lt;code&gt;glab --version&lt;/code&gt; を実行して、インストールが正しくできていることを確認してください。&lt;/p&gt;
&lt;p&gt;OS ごとの主要なインストールコマンドは以下の通りです。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;OS&lt;/th&gt;
 &lt;th&gt;インストールコマンド&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;macOS&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;brew install glab&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Windows (winget)&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;winget install glab&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Windows (scoop)&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;scoop install glab&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Linux (Ubuntu/Debian)&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;sudo apt install glab&lt;/code&gt;（※公式リポジトリ推奨）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;インストール後、&lt;code&gt;glab --version&lt;/code&gt; で正常にインストールされたか確認しましょう。&lt;/p&gt;
&lt;p&gt;バージョンが古かったり、上記でインストールできない場合は、公式リリースからダウンロードしてインストールします。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gitlab.com/gitlab-org/cli/-/releases" target="_blank" rel="noopener"
 &gt;https://gitlab.com/gitlab-org/cli/-/releases&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例えば以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /tmp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget https://gitlab.com/gitlab-org/cli/-/releases/v1.97.0/downloads/glab_1.97.0_linux_amd64.deb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo dpkg -i glab_1.97.0_linux_amd64.deb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="2-初期設定認証"&gt;&lt;a href="#2-%e5%88%9d%e6%9c%9f%e8%a8%ad%e5%ae%9a%e8%aa%8d%e8%a8%bc" class="header-anchor"&gt;&lt;/a&gt;2. 初期設定（認証）
&lt;/h2&gt;&lt;p&gt;インストールが完了したら、GitLab アカウントと連携させます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;glab auth login
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実行すると対話形式で以下の項目を聞かれます：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;GitLab インスタンスの種類&lt;/strong&gt;: GitLab.com か 自前運用のサーバー（Self-Managed）かを選択。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;認証方法&lt;/strong&gt;: &lt;code&gt;Web&lt;/code&gt; を選択するとブラウザが開いて簡単に認証できます。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;プロトコル&lt;/strong&gt;: &lt;code&gt;SSH&lt;/code&gt; または &lt;code&gt;HTTPS&lt;/code&gt; を選択。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;設定が完了すると、&lt;code&gt;~/.config/glab-cli/config.yml&lt;/code&gt; に設定が保存されます。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="3-devcontainer-での認証情報共有"&gt;&lt;a href="#3-devcontainer-%e3%81%a7%e3%81%ae%e8%aa%8d%e8%a8%bc%e6%83%85%e5%a0%b1%e5%85%b1%e6%9c%89" class="header-anchor"&gt;&lt;/a&gt;3. devcontainer での認証情報共有
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;glab&lt;/code&gt; の認証情報は &lt;code&gt;~/.config/glab-cli/config.yml&lt;/code&gt; に保存されます。devcontainer をリビルドするとコンテナ内の &lt;code&gt;~/.config/glab-cli&lt;/code&gt; が消えて再ログインが必要になるため、ホスト側の設定を bind mount で共有しておくと便利です。&lt;/p&gt;
&lt;p&gt;一般的には、&lt;code&gt;.devcontainer/devcontainer.json&lt;/code&gt; の &lt;code&gt;mounts&lt;/code&gt; にホストの &lt;code&gt;~/.config/glab-cli&lt;/code&gt; を追加します。例:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-jsonc" data-lang="jsonc"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;mounts&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;source=${localEnv:HOME}/.config/glab-cli,target=/home/vscode/.config/glab-cli,type=bind,consistency=cached&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;もし &lt;code&gt;gh&lt;/code&gt; など別の CLI も devcontainer 内で使うなら、同じように &lt;code&gt;~/.config/gh&lt;/code&gt; を共有することもできます。&lt;/p&gt;
&lt;p&gt;ホスト側に &lt;code&gt;~/.config/glab-cli&lt;/code&gt; が存在していれば、ホストで一度 &lt;code&gt;glab auth login&lt;/code&gt; しておけばコンテナ側でも同じ認証を使えます。ホストにディレクトリがない場合は、&lt;code&gt;mkdir -p ~/.config/glab-cli&lt;/code&gt; で空ディレクトリを作成しておけばマウントが通ります。&lt;/p&gt;
&lt;p&gt;このようにしておけば、&lt;code&gt;glab&lt;/code&gt; の認証設定をホストと devcontainer で共通化し、コンテナ再構築後も再ログイン不要で作業を続けやすくなります。&lt;/p&gt;
&lt;h2 id="4-よく使う基本コマンド集"&gt;&lt;a href="#4-%e3%82%88%e3%81%8f%e4%bd%bf%e3%81%86%e5%9f%ba%e6%9c%ac%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e9%9b%86" class="header-anchor"&gt;&lt;/a&gt;4. よく使う基本コマンド集
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;glab&lt;/code&gt; のコマンド体系は &lt;code&gt;glab &amp;lt;リソース名&amp;gt; &amp;lt;アクション&amp;gt;&lt;/code&gt; という形式で、&lt;code&gt;gh&lt;/code&gt; と非常に似ています。&lt;/p&gt;
&lt;h3 id="-merge-request-mr-を操作する"&gt;&lt;a href="#-merge-request-mr-%e3%82%92%e6%93%8d%e4%bd%9c%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;■ Merge Request (MR) を操作する
&lt;/h3&gt;&lt;p&gt;開発のメイン作業となる MR 操作です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MR の一覧表示&lt;/strong&gt;: &lt;code&gt;glab mr list&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MR の作成&lt;/strong&gt;: &lt;code&gt;glab mr create --fill&lt;/code&gt;（現在のブランチから自動入力で作成）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MR の詳細表示&lt;/strong&gt;: &lt;code&gt;glab mr view &amp;lt;id&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MR を承認&lt;/strong&gt;: &lt;code&gt;glab mr approve &amp;lt;id&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MR をマージ&lt;/strong&gt;: &lt;code&gt;glab mr merge &amp;lt;id&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="-issue-課題-を管理する"&gt;&lt;a href="#-issue-%e8%aa%b2%e9%a1%8c-%e3%82%92%e7%ae%a1%e7%90%86%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;■ Issue (課題) を管理する
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Issue 一覧&lt;/strong&gt;: &lt;code&gt;glab issue list&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Issue 作成&lt;/strong&gt;: &lt;code&gt;glab issue create -t &amp;quot;タイトル&amp;quot; -description &amp;quot;内容&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="-cicd-パイプラインを確認する"&gt;&lt;a href="#-cicd-%e3%83%91%e3%82%a4%e3%83%97%e3%83%a9%e3%82%a4%e3%83%b3%e3%82%92%e7%a2%ba%e8%aa%8d%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;■ CI/CD パイプラインを確認する
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;glab&lt;/code&gt; 独自の強力な機能の一つが、CI パイプラインのリアルタイム監視です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;パイプラインの状態表示&lt;/strong&gt;: &lt;code&gt;glab pipeline status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;実行中のログをリアルタイム表示&lt;/strong&gt;: &lt;code&gt;glab pipeline ci view&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;失敗したジョブの再実行&lt;/strong&gt;: &lt;code&gt;glab ci retry&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="4-gh-と-glab-の主な対応表"&gt;&lt;a href="#4-gh-%e3%81%a8-glab-%e3%81%ae%e4%b8%bb%e3%81%aa%e5%af%be%e5%bf%9c%e8%a1%a8" class="header-anchor"&gt;&lt;/a&gt;4. &lt;code&gt;gh&lt;/code&gt; と &lt;code&gt;glab&lt;/code&gt; の主な対応表
&lt;/h2&gt;&lt;p&gt;GitHub CLI に慣れている方向けのクイック比較です。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;機能&lt;/th&gt;
 &lt;th&gt;GitHub (&lt;code&gt;gh&lt;/code&gt;)&lt;/th&gt;
 &lt;th&gt;GitLab (&lt;code&gt;glab&lt;/code&gt;)&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;認証&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;gh auth login&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;glab auth login&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;PR / MR 作成&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;gh pr create&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;&lt;code&gt;glab mr create&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;PR / MR チェックアウト&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;gh pr checkout &amp;lt;id&amp;gt;&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;&lt;code&gt;glab mr checkout &amp;lt;id&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;リポジトリ作成&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;gh repo create&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;&lt;code&gt;glab project create&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;CI 監視&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;gh run watch&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;&lt;code&gt;glab pipeline ci view&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="5-自社運用の-gitlab-self-managed-で使うコツ"&gt;&lt;a href="#5-%e8%87%aa%e7%a4%be%e9%81%8b%e7%94%a8%e3%81%ae-gitlab-self-managed-%e3%81%a7%e4%bd%bf%e3%81%86%e3%82%b3%e3%83%84" class="header-anchor"&gt;&lt;/a&gt;5. 自社運用の GitLab (Self-Managed) で使うコツ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;glab&lt;/code&gt; は GitLab.com だけでなく、会社などで独自に立てている GitLab サーバーでも使えます。その場合、環境変数でホストを指定しておくと便利です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;GITLAB_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gitlab.example.com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="まとめ"&gt;&lt;a href="#%e3%81%be%e3%81%a8%e3%82%81" class="header-anchor"&gt;&lt;/a&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;glab&lt;/code&gt; を導入することで、「コードを書く → プッシュする → ブラウザで MR を作る → CI の完了を待つ」という一連の流れをターミナルから一歩も出ずに行えるようになります。&lt;/p&gt;
&lt;p&gt;まずは &lt;code&gt;glab mr list&lt;/code&gt; から始めて、快適な GitLab ライフを送りましょう！&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;参考リンク:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.gitlab.com/ee/editor_extensions/gitlab_cli/" target="_blank" rel="noopener"
 &gt;GitLab CLI 公式ドキュメント&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://gitlab.com/gitlab-org/cli" target="_blank" rel="noopener"
 &gt;GitHub リポジトリ (gitlab-org/cli)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>GitHub CLI (gh) のインストールと基本的な使い方</title><link>https://blog.ponkotools.com/posts/2026/05/09/github-cli/</link><pubDate>Sat, 09 May 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/05/09/github-cli/</guid><description>&lt;p&gt;GitHub CLI (&lt;code&gt;gh&lt;/code&gt;) は、GitHub が公式に提供しているコマンドラインツールです。&lt;/p&gt;
&lt;p&gt;ブラウザを開かなくても、リポジトリの clone、Issue の確認、Pull Request の作成、GitHub Actions の実行状況確認などをターミナルから操作できます。Git と組み合わせて使うと、日常の GitHub 作業をかなり短い導線にできます。&lt;/p&gt;
&lt;p&gt;この記事では、Windows と Ubuntu で &lt;code&gt;gh&lt;/code&gt; をインストールし、最初に覚えておくと便利な基本コマンドをまとめます。&lt;/p&gt;
&lt;h2 id="gh-でできること"&gt;&lt;a href="#gh-%e3%81%a7%e3%81%a7%e3%81%8d%e3%82%8b%e3%81%93%e3%81%a8" class="header-anchor"&gt;&lt;/a&gt;gh でできること
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;gh&lt;/code&gt; を使うと、たとえば以下のような作業をターミナルから実行できます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GitHub へのログイン&lt;/li&gt;
&lt;li&gt;リポジトリの clone / 作成 / 表示&lt;/li&gt;
&lt;li&gt;Issue の一覧表示 / 作成 / 表示&lt;/li&gt;
&lt;li&gt;Pull Request の一覧表示 / 作成 / checkout / merge&lt;/li&gt;
&lt;li&gt;GitHub Actions の workflow / run の確認&lt;/li&gt;
&lt;li&gt;ブラウザで現在のリポジトリや PR を開く&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;GitHub の画面を見に行く回数を減らせるので、コードを書いている流れを止めにくいのが大きなメリットです。&lt;/p&gt;
&lt;h2 id="インストール"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;インストール
&lt;/h2&gt;&lt;h3 id="windows-にインストールする"&gt;&lt;a href="#windows-%e3%81%ab%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;Windows にインストールする
&lt;/h3&gt;&lt;p&gt;Windows では、公式手順として WinGet を使う方法が一番簡単です。&lt;/p&gt;
&lt;p&gt;PowerShell または Windows Terminal を開いて、以下を実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;winget&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-id&lt;/span&gt; &lt;span class="n"&gt;GitHub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;cli
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;インストール後、ターミナルを開き直して確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;gh&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;バージョン情報が表示されればインストール完了です。&lt;/p&gt;
&lt;p&gt;アップデートする場合は以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;winget&lt;/span&gt; &lt;span class="n"&gt;upgrade&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-id&lt;/span&gt; &lt;span class="n"&gt;GitHub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;cli
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;もし WinGet を使わない場合は、GitHub CLI の Releases ページから MSI インストーラーをダウンロードして導入することもできます。&lt;/p&gt;
&lt;h3 id="ubuntu-にインストールする"&gt;&lt;a href="#ubuntu-%e3%81%ab%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;Ubuntu にインストールする
&lt;/h3&gt;&lt;p&gt;Ubuntu では、標準の apt リポジトリからそのままインストールできます。&lt;/p&gt;
&lt;p&gt;まずパッケージ情報を更新してから、&lt;code&gt;gh&lt;/code&gt; をインストールします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install gh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh --version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;アップデートする場合は、通常の apt パッケージと同じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install gh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;もし apt で見つからない場合や、GitHub CLI の最新版を追いたい場合は、GitHub CLI 公式リポジトリを追加する方法もあります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;type&lt;/span&gt; -p wget &amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;sudo apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo apt install wget -y&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo mkdir -p -m &lt;span class="m"&gt;755&lt;/span&gt; /etc/apt/keyrings
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget -nv -O /tmp/githubcli-archive-keyring.gpg https://cli.github.com/packages/githubcli-archive-keyring.gpg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo cp /tmp/githubcli-archive-keyring.gpg /etc/apt/keyrings/githubcli-archive-keyring.gpg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo mkdir -p -m &lt;span class="m"&gt;755&lt;/span&gt; /etc/apt/sources.list.d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;deb [arch=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dpkg --print-architecture&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee /etc/apt/sources.list.d/github-cli.list &amp;gt; /dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install gh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;通常利用なら、まずは &lt;code&gt;sudo apt install gh&lt;/code&gt; で十分です。&lt;/p&gt;
&lt;h2 id="初期設定-github-にログインする"&gt;&lt;a href="#%e5%88%9d%e6%9c%9f%e8%a8%ad%e5%ae%9a-github-%e3%81%ab%e3%83%ad%e3%82%b0%e3%82%a4%e3%83%b3%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;初期設定: GitHub にログインする
&lt;/h2&gt;&lt;p&gt;インストールできたら、GitHub アカウントでログインします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh auth login
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;対話形式でいくつか質問されます。個人利用で GitHub.com を使うなら、だいたい以下の選択で問題ありません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Where do you use GitHub? GitHub.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? What is your preferred protocol for Git operations? HTTPS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Authenticate Git with your GitHub credentials? Yes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? How would you like to authenticate GitHub CLI? Login with a web browser
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ポイントは、&lt;code&gt;Authenticate Git with your GitHub credentials?&lt;/code&gt; で &lt;code&gt;Yes&lt;/code&gt; を選ぶことです。これにより、&lt;code&gt;gh&lt;/code&gt; だけでなく通常の &lt;code&gt;git push&lt;/code&gt; や &lt;code&gt;git fetch&lt;/code&gt; の HTTPS 認証も &lt;code&gt;gh&lt;/code&gt; に任せられます。&lt;/p&gt;
&lt;p&gt;ブラウザが開いたら GitHub にログインして認証します。WSL やサーバー上などブラウザを開きにくい環境では、表示されたワンタイムコードを手元のブラウザで入力して認証します。&lt;/p&gt;
&lt;p&gt;ログイン状態は以下で確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh auth status
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="普通の-git-コマンドでも-gh-の認証情報は使われる"&gt;&lt;a href="#%e6%99%ae%e9%80%9a%e3%81%ae-git-%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e3%81%a7%e3%82%82-gh-%e3%81%ae%e8%aa%8d%e8%a8%bc%e6%83%85%e5%a0%b1%e3%81%af%e4%bd%bf%e3%82%8f%e3%82%8c%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;普通の git コマンドでも gh の認証情報は使われる？
&lt;/h2&gt;&lt;p&gt;使われます。ただし、&lt;code&gt;gh auth login&lt;/code&gt; の途中で以下を選んでいることが前提です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;? Authenticate Git with your GitHub credentials? Yes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この設定を有効にすると、&lt;code&gt;gh&lt;/code&gt; が Git の credential helper として設定されます。そのため、以下のような普通の Git コマンドでも、&lt;code&gt;gh&lt;/code&gt; でログインした認証情報が利用されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git fetch origin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git pull
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git push origin main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;確認するには、Git の credential helper 設定を見ます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git config --global --get credential.helper
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;環境によって表示は少し違いますが、&lt;code&gt;gh auth git-credential&lt;/code&gt; を使う設定になっていれば OK です。&lt;/p&gt;
&lt;p&gt;注意点として、この仕組みが使われるのは基本的に HTTPS の remote URL です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git remote -v
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;remote URL が以下のようになっていれば、HTTPS 経由です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;origin https://github.com/OWNER/REPO.git (fetch)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;origin https://github.com/OWNER/REPO.git (push)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一方で、&lt;code&gt;git@github.com:OWNER/REPO.git&lt;/code&gt; のような SSH の remote URL を使っている場合は、Git の認証は SSH key 側で行われます。この場合でも &lt;code&gt;gh&lt;/code&gt; コマンド自体の GitHub API 操作には、&lt;code&gt;gh auth login&lt;/code&gt; の認証情報が使われます。&lt;/p&gt;
&lt;h2 id="よく使う基本コマンド"&gt;&lt;a href="#%e3%82%88%e3%81%8f%e4%bd%bf%e3%81%86%e5%9f%ba%e6%9c%ac%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;よく使う基本コマンド
&lt;/h2&gt;&lt;p&gt;ここからは、最初に覚えておくと便利なコマンドです。&lt;/p&gt;
&lt;h3 id="リポジトリ操作"&gt;&lt;a href="#%e3%83%aa%e3%83%9d%e3%82%b8%e3%83%88%e3%83%aa%e6%93%8d%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;リポジトリ操作
&lt;/h3&gt;&lt;p&gt;リポジトリを clone します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh repo clone OWNER/REPO
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;たとえば GitHub CLI 本体のリポジトリなら以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh repo clone cli/cli
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;現在のリポジトリをブラウザで開きます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh repo view --web
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;新しいリポジトリを作成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh repo create
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;対話形式で公開範囲やローカルディレクトリの扱いを選べます。スクリプト化したい場合は、&lt;code&gt;--public&lt;/code&gt; や &lt;code&gt;--private&lt;/code&gt; などのオプションを付けて実行できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh repo create my-app --private --source&lt;span class="o"&gt;=&lt;/span&gt;. --remote&lt;span class="o"&gt;=&lt;/span&gt;origin
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="issue-操作"&gt;&lt;a href="#issue-%e6%93%8d%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;Issue 操作
&lt;/h3&gt;&lt;p&gt;Issue の一覧を表示します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh issue list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Issue の詳細を表示します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh issue view &lt;span class="m"&gt;123&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Issue を作成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh issue create --title &lt;span class="s2"&gt;&amp;#34;ログイン画面の文言を修正する&amp;#34;&lt;/span&gt; --body &lt;span class="s2"&gt;&amp;#34;ボタンの表記を変更する&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ブラウザで Issue を開きたい場合は &lt;code&gt;--web&lt;/code&gt; を付けます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh issue view &lt;span class="m"&gt;123&lt;/span&gt; --web
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="pull-request-操作"&gt;&lt;a href="#pull-request-%e6%93%8d%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;Pull Request 操作
&lt;/h3&gt;&lt;p&gt;Pull Request の一覧を表示します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh pr list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;現在のブランチから Pull Request を作成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh pr create
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コミットメッセージやブランチ情報からタイトル・本文を自動入力したい場合は &lt;code&gt;--fill&lt;/code&gt; が便利です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh pr create --fill
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pull Request の詳細を表示します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh pr view &lt;span class="m"&gt;123&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pull Request のブランチをローカルに checkout します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh pr checkout &lt;span class="m"&gt;123&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;レビューや CI の状態を確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh pr checks &lt;span class="m"&gt;123&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;マージします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh pr merge &lt;span class="m"&gt;123&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="github-actions-操作"&gt;&lt;a href="#github-actions-%e6%93%8d%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;GitHub Actions 操作
&lt;/h3&gt;&lt;p&gt;workflow の一覧を表示します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh workflow list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実行履歴を表示します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh run list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最新の workflow run を確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh run view
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実行中の workflow を待ちます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh run watch
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;失敗したジョブのログを確認する場合は、まず &lt;code&gt;gh run list&lt;/code&gt; で run ID を確認してから以下を実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh run view RUN_ID --log-failed
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="便利な使い方"&gt;&lt;a href="#%e4%be%bf%e5%88%a9%e3%81%aa%e4%bd%bf%e3%81%84%e6%96%b9" class="header-anchor"&gt;&lt;/a&gt;便利な使い方
&lt;/h2&gt;&lt;h3 id="現在のページをブラウザで開く"&gt;&lt;a href="#%e7%8f%be%e5%9c%a8%e3%81%ae%e3%83%9a%e3%83%bc%e3%82%b8%e3%82%92%e3%83%96%e3%83%a9%e3%82%a6%e3%82%b6%e3%81%a7%e9%96%8b%e3%81%8f" class="header-anchor"&gt;&lt;/a&gt;現在のページをブラウザで開く
&lt;/h3&gt;&lt;p&gt;現在のリポジトリを GitHub 上で開きます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh browse
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Issue や PR の URL を組み立てる必要がないので、地味に便利です。&lt;/p&gt;
&lt;h3 id="自分に関係する状況をまとめて見る"&gt;&lt;a href="#%e8%87%aa%e5%88%86%e3%81%ab%e9%96%a2%e4%bf%82%e3%81%99%e3%82%8b%e7%8a%b6%e6%b3%81%e3%82%92%e3%81%be%e3%81%a8%e3%82%81%e3%81%a6%e8%a6%8b%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;自分に関係する状況をまとめて見る
&lt;/h3&gt;&lt;p&gt;自分に関連する Issue、PR、レビュー依頼などを確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh status
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;朝の作業開始時に一度実行すると、見るべきものをざっと把握できます。&lt;/p&gt;
&lt;h3 id="エイリアスを作る"&gt;&lt;a href="#%e3%82%a8%e3%82%a4%e3%83%aa%e3%82%a2%e3%82%b9%e3%82%92%e4%bd%9c%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;エイリアスを作る
&lt;/h3&gt;&lt;p&gt;よく使うコマンドは短い別名を付けられます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh &lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; prs &lt;span class="s1"&gt;&amp;#39;pr list --author @me&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh prs
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この例では、自分が作成した Pull Request 一覧を &lt;code&gt;gh prs&lt;/code&gt; で表示できます。&lt;/p&gt;
&lt;h2 id="windows-と-ubuntu-で共通して気をつけること"&gt;&lt;a href="#windows-%e3%81%a8-ubuntu-%e3%81%a7%e5%85%b1%e9%80%9a%e3%81%97%e3%81%a6%e6%b0%97%e3%82%92%e3%81%a4%e3%81%91%e3%82%8b%e3%81%93%e3%81%a8" class="header-anchor"&gt;&lt;/a&gt;Windows と Ubuntu で共通して気をつけること
&lt;/h2&gt;&lt;h3 id="ターミナルを開き直す"&gt;&lt;a href="#%e3%82%bf%e3%83%bc%e3%83%9f%e3%83%8a%e3%83%ab%e3%82%92%e9%96%8b%e3%81%8d%e7%9b%b4%e3%81%99" class="header-anchor"&gt;&lt;/a&gt;ターミナルを開き直す
&lt;/h3&gt;&lt;p&gt;Windows ではインストーラーが PATH を更新します。&lt;code&gt;gh&lt;/code&gt; が見つからない場合は、Windows Terminal や PowerShell を開き直してください。&lt;/p&gt;
&lt;p&gt;Ubuntu でも、インストール後にシェルがコマンドの場所をキャッシュしている場合があります。うまく認識されないときは、ターミナルを開き直すか &lt;code&gt;hash -r&lt;/code&gt; を実行します。&lt;/p&gt;
&lt;h3 id="git-の認証方式をそろえる"&gt;&lt;a href="#git-%e3%81%ae%e8%aa%8d%e8%a8%bc%e6%96%b9%e5%bc%8f%e3%82%92%e3%81%9d%e3%82%8d%e3%81%88%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;Git の認証方式をそろえる
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;gh auth login&lt;/code&gt; で HTTPS を選び、Git の認証にも &lt;code&gt;gh&lt;/code&gt; を使う設定にした場合、リモート URL も HTTPS にしておくと扱いやすいです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git remote -v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git remote set-url origin https://github.com/OWNER/REPO.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;SSH を使いたい場合は、&lt;code&gt;gh auth login&lt;/code&gt; の対話で SSH を選び、SSH key の登録も &lt;code&gt;gh&lt;/code&gt; に任せることができます。HTTPS と SSH のどちらでも使えますが、チームや自分の環境で片方に寄せておくとトラブルシュートが楽です。&lt;/p&gt;
&lt;h3 id="github-enterprise-server-を使う場合"&gt;&lt;a href="#github-enterprise-server-%e3%82%92%e4%bd%bf%e3%81%86%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;GitHub Enterprise Server を使う場合
&lt;/h3&gt;&lt;p&gt;会社などで GitHub Enterprise Server を使っている場合は、ホスト名を指定してログインします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh auth login --hostname github.example.com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;通常の GitHub.com とは認証先が別になるため、&lt;code&gt;gh auth status&lt;/code&gt; でどのホストにログインしているか確認しておくと安心です。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;&lt;a href="#%e3%81%be%e3%81%a8%e3%82%81" class="header-anchor"&gt;&lt;/a&gt;まとめ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;gh&lt;/code&gt; を入れておくと、GitHub 上の操作をターミナルから自然に扱えるようになります。&lt;/p&gt;
&lt;p&gt;まずは以下の流れだけ覚えておけば十分です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh auth login
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh repo clone OWNER/REPO
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh issue list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh pr list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh pr create --fill
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh run list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;慣れてきたら &lt;code&gt;gh pr checkout&lt;/code&gt;、&lt;code&gt;gh pr checks&lt;/code&gt;、&lt;code&gt;gh run watch&lt;/code&gt; あたりを使うと、Pull Request と CI の確認がかなり楽になります。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://cli.github.com/" target="_blank" rel="noopener"
 &gt;GitHub CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://cli.github.com/manual/" target="_blank" rel="noopener"
 &gt;GitHub CLI Manual&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/cli/cli/blob/trunk/docs/install_windows.md" target="_blank" rel="noopener"
 &gt;Installing gh on Windows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/cli/cli/blob/trunk/docs/install_linux.md" target="_blank" rel="noopener"
 &gt;Installing gh on Linux and BSD&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>ブログ移転の報告</title><link>https://blog.ponkotools.com/posts/2026/04/28/blog/</link><pubDate>Tue, 28 Apr 2026 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2026/04/28/blog/</guid><description>&lt;h2 id="移転しました"&gt;&lt;a href="#%e7%a7%bb%e8%bb%a2%e3%81%97%e3%81%be%e3%81%97%e3%81%9f" class="header-anchor"&gt;&lt;/a&gt;移転しました
&lt;/h2&gt;&lt;p&gt;Blogger で作成していたブログを、こちらに移転しました。&lt;/p&gt;
&lt;p&gt;最近は生成 AI が当たり前になり、自分で調べものをすることも少なくなって、記事もあまり書けていませんでしたが、これからも細々と続けていきたいと思います。&lt;/p&gt;
&lt;p&gt;過去の記事についてはまだ全て移動できていませんが、少しずつ移動させていきます。&lt;/p&gt;</description></item><item><title>Jekyll で asciidoctor-diagram を使う</title><link>https://blog.ponkotools.com/posts/2025/05/27/jekyll/</link><pubDate>Tue, 27 May 2025 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2025/05/27/jekyll/</guid><description>&lt;p&gt;Jekyll で Asciidoc を使えるようにしたのですが、Asciidoc 内でダイアグラムを使うためには以下の設定が必要です。&lt;/p&gt;
&lt;h2 id="asciidoctor-diagram-の有効化"&gt;&lt;a href="#asciidoctor-diagram-%e3%81%ae%e6%9c%89%e5%8a%b9%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;Asciidoctor Diagram の有効化
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Gemfile&lt;/code&gt; に以下を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;group :jekyll_plugins do
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; gem &amp;#39;asciidoctor-diagram&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; gem &amp;#39;asciidoctor-diagram-plantuml&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;end
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下のページには記述がありませんでしたが、私の環境では &lt;code&gt;asciidoctor-diagram-plantuml&lt;/code&gt; も必要でした。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/asciidoctor/jekyll-asciidoc?tab=readme-ov-file#enabling-asciidoctor-diagram" target="_blank" rel="noopener"
 &gt;https://github.com/asciidoctor/jekyll-asciidoc?tab=readme-ov-file#enabling-asciidoctor-diagram&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="生成された画像の保存"&gt;&lt;a href="#%e7%94%9f%e6%88%90%e3%81%95%e3%82%8c%e3%81%9f%e7%94%bb%e5%83%8f%e3%81%ae%e4%bf%9d%e5%ad%98" class="header-anchor"&gt;&lt;/a&gt;生成された画像の保存
&lt;/h2&gt;&lt;p&gt;Jekyll に、ビルドプロセスの途中で Asciidoctor Diagram が出力した画像ファイルを削除しないよう指示するために、 &lt;code&gt;_plugins/jekyll-ext.rb&lt;/code&gt; を作成し、以下を記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;class Jekyll::Cleaner
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; def cleanup!; end
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;end
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;詳細は以下をご参照ください。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/asciidoctor/jekyll-asciidoc?tab=readme-ov-file#preserving-generated-images" target="_blank" rel="noopener"
 &gt;https://github.com/asciidoctor/jekyll-asciidoc?tab=readme-ov-file#preserving-generated-images&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/asciidoctor/jekyll-asciidoc" target="_blank" rel="noopener"
 &gt;https://github.com/asciidoctor/jekyll-asciidoc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Jekyll で画像を記事と同じフォルダに置く</title><link>https://blog.ponkotools.com/posts/2025/03/21/jekyll/</link><pubDate>Fri, 21 Mar 2025 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2025/03/21/jekyll/</guid><description>&lt;p&gt;Jekyll では画像などは &lt;code&gt;assets&lt;/code&gt; 配下に置くのが普通で、&lt;code&gt;_post&lt;/code&gt; などに置いてもその中の画像は &lt;code&gt;_site&lt;/code&gt; には出力されません。&lt;/p&gt;
&lt;p&gt;しかし、記事内からのみ参照する画像は記事と同じフォルダにあったほうが管理しやすいです。
これについては、&lt;code&gt;jekyll-postfiles&lt;/code&gt; というプラグインを使うことで解決できました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://nhoizey.github.io/jekyll-postfiles/" target="_blank" rel="noopener"
 &gt;https://nhoizey.github.io/jekyll-postfiles/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;インストール方法は、&lt;code&gt;Gemfile&lt;/code&gt; に以下を追記するだけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="ss"&gt;:jekyll_plugins&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;jekyll-postfiles&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://nhoizey.github.io/jekyll-postfiles/" target="_blank" rel="noopener"
 &gt;https://nhoizey.github.io/jekyll-postfiles/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Jekyll で Minimal Mistakes のテーマを適用する</title><link>https://blog.ponkotools.com/posts/2024/12/19/jekyll/</link><pubDate>Thu, 19 Dec 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/12/19/jekyll/</guid><description>&lt;p&gt;いろいろテーマを探してみましたが、多機能かつドキュメントが充実していたのでこれにしてみました。&lt;/p&gt;
&lt;p&gt;以下の記事で作成した環境に対して適用します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2024/09/jekyll-docker.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2024/09/jekyll-docker.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;尚、デモページ、およびドキュメントは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mmistakes/minimal-mistakes" target="_blank" rel="noopener"
 &gt;https://github.com/mmistakes/minimal-mistakes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="テーマの適用"&gt;&lt;a href="#%e3%83%86%e3%83%bc%e3%83%9e%e3%81%ae%e9%81%a9%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;テーマの適用
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Gemfile&lt;/code&gt; に以下を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;minimal-mistakes-jekyll&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;_cofig.yml&lt;/code&gt; でテーマを指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;minimal-mistakes-jekyll&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;必要に応じて各記事のレイアウトを変更します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;single&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;選択できるレイアウトについては以下を参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/layouts/" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/layouts/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;テーマを適用するだけならこれだけで OK でした。&lt;/p&gt;
&lt;h2 id="その他の設定"&gt;&lt;a href="#%e3%81%9d%e3%81%ae%e4%bb%96%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;その他の設定
&lt;/h2&gt;&lt;p&gt;公式のドキュメントに詳しく書かれているので、ここでは個人的に必要なものだけ抜粋して記載します。&lt;/p&gt;
&lt;h3 id="スキンを変更する"&gt;&lt;a href="#%e3%82%b9%e3%82%ad%e3%83%b3%e3%82%92%e5%a4%89%e6%9b%b4%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;スキンを変更する
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/configuration/#skin" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/configuration/#skin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;_config.yml&lt;/code&gt; に以下のように記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;minimal_mistakes_skin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="記事内の目次を作成する"&gt;&lt;a href="#%e8%a8%98%e4%ba%8b%e5%86%85%e3%81%ae%e7%9b%ae%e6%ac%a1%e3%82%92%e4%bd%9c%e6%88%90%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;記事内の目次を作成する
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/layouts/#table-of-contents" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/layouts/#table-of-contents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;フロントマターで以下のように設定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;toc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;toc_label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;My Table of Contents&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;toc_icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cog&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="記事を広げる"&gt;&lt;a href="#%e8%a8%98%e4%ba%8b%e3%82%92%e5%ba%83%e3%81%92%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;記事を広げる
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/layouts/#wide-page" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/layouts/#wide-page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;記事を目次のスペースまで広げるには、フロントマターで以下を設定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;wide&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ページの作成"&gt;&lt;a href="#%e3%83%9a%e3%83%bc%e3%82%b8%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;ページの作成
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;_pages&lt;/code&gt; というフォルダを作成し、そこに記事を追加します。&lt;br&gt;
&lt;code&gt;_config.yml&lt;/code&gt; に以下を追加し、&lt;code&gt;_pages&lt;/code&gt; フォルダのドキュメントを変換対象に指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="カテゴリごとの記事一覧ページを作成"&gt;&lt;a href="#%e3%82%ab%e3%83%86%e3%82%b4%e3%83%aa%e3%81%94%e3%81%a8%e3%81%ae%e8%a8%98%e4%ba%8b%e4%b8%80%e8%a6%a7%e3%83%9a%e3%83%bc%e3%82%b8%e3%82%92%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;カテゴリごとの記事一覧ページを作成
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/layouts/#archive-layout" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/layouts/#archive-layout&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;_pages&lt;/code&gt; に &lt;code&gt;category-archive.md&lt;/code&gt; というファイルを作成し、以下のような内容を記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Posts by Category&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;categories&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;permalink&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/categories/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;author_profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="タグごとの記事一覧ページを作成"&gt;&lt;a href="#%e3%82%bf%e3%82%b0%e3%81%94%e3%81%a8%e3%81%ae%e8%a8%98%e4%ba%8b%e4%b8%80%e8%a6%a7%e3%83%9a%e3%83%bc%e3%82%b8%e3%82%92%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;タグごとの記事一覧ページを作成
&lt;/h3&gt;&lt;p&gt;カテゴリとほぼ同じです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/layouts/#archive-layout" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/layouts/#archive-layout&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;_pages&lt;/code&gt; に &lt;code&gt;tag-archive.md&lt;/code&gt; というファイルを作成し、以下のような内容を記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Posts by Tag&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;permalink&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/tags/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;tags&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;author_profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="年ごとの記事一覧ページを作成"&gt;&lt;a href="#%e5%b9%b4%e3%81%94%e3%81%a8%e3%81%ae%e8%a8%98%e4%ba%8b%e4%b8%80%e8%a6%a7%e3%83%9a%e3%83%bc%e3%82%b8%e3%82%92%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;年ごとの記事一覧ページを作成
&lt;/h3&gt;&lt;p&gt;カテゴリとほぼ同じです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/layouts/#archive-layout" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/layouts/#archive-layout&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;_pages&lt;/code&gt; に &lt;code&gt;year-achive.md&lt;/code&gt; というファイルを作成し、以下のような内容を記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Posts by Year&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;permalink&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/year-archive/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;posts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;author_profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="サイドバーを作成する"&gt;&lt;a href="#%e3%82%b5%e3%82%a4%e3%83%89%e3%83%90%e3%83%bc%e3%82%92%e4%bd%9c%e6%88%90%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;サイドバーを作成する
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/layouts/#custom-sidebar-navigation-menu" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/layouts/#custom-sidebar-navigation-menu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/layout-sidebar-nav-list/" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/layout-sidebar-nav-list/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/layout-sidebar-custom/" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/layout-sidebar-custom/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;_data/navigation.yml&lt;/code&gt; を作成し、以下のような内容を記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Getting Started&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Quick-Start Guide&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/quick-start-guide/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Structure&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/structure/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Installation&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/installation/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Upgrading&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/upgrading/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Customization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Configuration&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/configuration/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Navigation&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/navigation/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;UI Text&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/ui-text/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Authors&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/authors/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Layouts&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/layouts/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Content&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Working with Posts&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/posts/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Working with Pages&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/pages/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Working with Collections&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/collections/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Helpers&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/helpers/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Utility Classes&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/utility-classes/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Extras&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Stylesheets&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/stylesheets/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;JavaScript&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/javascript/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;サイドバーを表示させたい記事のフロントマターに以下を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;docs&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;全ての記事に表示したい場合は、&lt;code&gt;_config.yml&lt;/code&gt; で以下のようにデフォルト値を設定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;docs&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;show_date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="画面上部にナビゲーションを作成する"&gt;&lt;a href="#%e7%94%bb%e9%9d%a2%e4%b8%8a%e9%83%a8%e3%81%ab%e3%83%8a%e3%83%93%e3%82%b2%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3%e3%82%92%e4%bd%9c%e6%88%90%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;画面上部にナビゲーションを作成する
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/navigation/" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/navigation/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;_data/navigation.yml&lt;/code&gt; を作成し、以下のような内容を記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Quick-Start Guide&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/docs/quick-start-guide/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Posts&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/year-archive/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Categories&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/categories/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Tags&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/tags/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Pages&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/page-archive/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Collections&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/collection-archive/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;External Link&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://google.com&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;_blank&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="記事に投稿日を表示"&gt;&lt;a href="#%e8%a8%98%e4%ba%8b%e3%81%ab%e6%8a%95%e7%a8%bf%e6%97%a5%e3%82%92%e8%a1%a8%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;記事に投稿日を表示
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/configuration/#post-dates" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/configuration/#post-dates&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;_config.yml&lt;/code&gt; に以下を設定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;posts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;show_date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="投稿日のフォーマットを指定"&gt;&lt;a href="#%e6%8a%95%e7%a8%bf%e6%97%a5%e3%81%ae%e3%83%95%e3%82%a9%e3%83%bc%e3%83%9e%e3%83%83%e3%83%88%e3%82%92%e6%8c%87%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;投稿日のフォーマットを指定
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/configuration/#post-dates" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/configuration/#post-dates&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;_config.yml&lt;/code&gt; で以下のように設定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;date_format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;%Y-%m-%d&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="コードブロックにコピーボタンを付ける"&gt;&lt;a href="#%e3%82%b3%e3%83%bc%e3%83%89%e3%83%96%e3%83%ad%e3%83%83%e3%82%af%e3%81%ab%e3%82%b3%e3%83%94%e3%83%bc%e3%83%9c%e3%82%bf%e3%83%b3%e3%82%92%e4%bb%98%e3%81%91%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;コードブロックにコピーボタンを付ける
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/configuration/#code-block-copy-button" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/configuration/#code-block-copy-button&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;_config.yml&lt;/code&gt; に以下を設定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;enable_copy_code_button&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="サイト内検索を有効にする"&gt;&lt;a href="#%e3%82%b5%e3%82%a4%e3%83%88%e5%86%85%e6%a4%9c%e7%b4%a2%e3%82%92%e6%9c%89%e5%8a%b9%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;サイト内検索を有効にする
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/configuration/#site-search" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/configuration/#site-search&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;_config.yml&lt;/code&gt; に以下を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;search&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;検索エンジンは変更できるようです（上記リンク参照）。&lt;/p&gt;
&lt;h3 id="パンくずリストの作成"&gt;&lt;a href="#%e3%83%91%e3%83%b3%e3%81%8f%e3%81%9a%e3%83%aa%e3%82%b9%e3%83%88%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;パンくずリストの作成
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/configuration/#breadcrumb-navigation-beta" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/configuration/#breadcrumb-navigation-beta&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://mmistakes.github.io/minimal-mistakes/docs/configuration/#archive-settings" target="_blank" rel="noopener"
 &gt;https://mmistakes.github.io/minimal-mistakes/docs/configuration/#archive-settings&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gwenneg.com/2024/08/17/blogging-with-minimal-effort.html" target="_blank" rel="noopener"
 &gt;https://gwenneg.com/2024/08/17/blogging-with-minimal-effort.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>docker コンテナ起動時に /tmp ディレクトリの中身を削除する</title><link>https://blog.ponkotools.com/posts/2024/12/11/docker/</link><pubDate>Wed, 11 Dec 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/12/11/docker/</guid><description>&lt;p&gt;Linux ではシステム起動時に &lt;code&gt;/tmp&lt;/code&gt; ディレクトリの中身がクリアされます。&lt;br&gt;
しかし、docker コンテナの場合は、通常はコンテナを再起動しても &lt;code&gt;/tmp&lt;/code&gt; ディレクトリの中身はクリアされません。&lt;/p&gt;
&lt;p&gt;docker コンテナで起動時に &lt;code&gt;/tmp&lt;/code&gt; ディレクトリの中身をクリアするには、以下のように &lt;code&gt;tmpfs&lt;/code&gt; ボリュームを使用する方法があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run --tmpfs /tmp my_image
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;docker compose の場合は以下のように指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;my_service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;my_image&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;tmpfs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/tmp&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# その他の設定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;尚、docker compose で手動でボリュームを再作成したい場合は、以下のように &lt;code&gt;docker compose down -v&lt;/code&gt; コマンドを使用して既存のボリュームを削除し、その後 &lt;code&gt;docker compose up -d&lt;/code&gt; コマンドで新しいボリュームを作成してコンテナを起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker compose down -v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;</description></item><item><title>Stable Diffusion web UI を動かしてみた</title><link>https://blog.ponkotools.com/posts/2024/12/10/stable-diffution/</link><pubDate>Tue, 10 Dec 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/12/10/stable-diffution/</guid><description>&lt;p&gt;ローカル環境で画像生成AIを使いたかったので、docker を使って Stable Diffusion web UI を動かしてみました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;docker 24.0.7&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="手順"&gt;&lt;a href="#%e6%89%8b%e9%a0%86" class="header-anchor"&gt;&lt;/a&gt;手順
&lt;/h2&gt;&lt;p&gt;Stable Diffusion web UI のリポジトリは以下になります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/AUTOMATIC1111/stable-diffusion-webui" target="_blank" rel="noopener"
 &gt;https://github.com/AUTOMATIC1111/stable-diffusion-webui&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Docker 版のリポジトリは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/AbdBarho/stable-diffusion-webui-docker" target="_blank" rel="noopener"
 &gt;https://github.com/AbdBarho/stable-diffusion-webui-docker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;まずはクローンしてきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git clone https://github.com/AbdBarho/stable-diffusion-webui-docker.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとは基本的に &lt;a class="link" href="https://github.com/AbdBarho/stable-diffusion-webui-docker/wiki/Setup" target="_blank" rel="noopener"
 &gt;Setup&lt;/a&gt; に記載されている通りにすすめるだけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="n"&gt;stable&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;diffusion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;webui&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;compose&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt; &lt;span class="n"&gt;download&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;compose&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt; &lt;span class="n"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;しかし、私の場合、&lt;code&gt;docker compose --profile auto up --build&lt;/code&gt; を実行したときにいくつかエラーが発生しました。&lt;/p&gt;
&lt;p&gt;最初に発生したエラーは以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt; &lt;span class="n"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;mount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="n"&gt;fonts&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dejavu&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt; &lt;span class="n"&gt;rsync&lt;/span&gt; &lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;jq&lt;/span&gt; &lt;span class="n"&gt;moreutils&lt;/span&gt; &lt;span class="n"&gt;aria2&lt;/span&gt; &lt;span class="n"&gt;ffmpeg&lt;/span&gt; &lt;span class="n"&gt;libglfw3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; &lt;span class="n"&gt;libgles2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mesa&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; &lt;span class="n"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="n"&gt;libcairo2&lt;/span&gt; &lt;span class="n"&gt;libcairo2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;essential&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;mount&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt; &lt;span class="n"&gt;requires&lt;/span&gt; &lt;span class="n"&gt;BuildKit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Refer&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;go&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;buildkit&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;learn&lt;/span&gt; &lt;span class="n"&gt;how&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;BuildKit&lt;/span&gt; &lt;span class="n"&gt;enabled&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Service&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;auto&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Build&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;生成AIに聞いてみた結果、どうやら buildx を手動でインストールする必要があるみたいでした。&lt;/p&gt;
&lt;p&gt;まずバイナリをダウンロードします:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -SL https://github.com/docker/buildx/releases/download/v0.10.4/buildx-v0.10.4.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ダウンロードしたファイルに実行権限を付与します:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod a+x ~/.docker/cli-plugins/docker-buildx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Docker Buildx が正しくインストールされたことを確認します:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker buildx version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで &lt;code&gt;docker buildx&lt;/code&gt; コマンドが利用できるようになります。&lt;br&gt;
再度 &lt;code&gt;docker-compose --profile auto up --build&lt;/code&gt; を実行したところ、今度は以下のエラーが発生しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | Installing extension dependencies (if any)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | Traceback (most recent call last):
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | File &amp;#34;/stable-diffusion-webui/webui.py&amp;#34;, line 13, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | initialize.imports()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | File &amp;#34;/stable-diffusion-webui/modules/initialize.py&amp;#34;, line 23, in imports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | import gradio # noqa: F401
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | File &amp;#34;/opt/conda/lib/python3.10/site-packages/gradio/__init__.py&amp;#34;, line 3, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | import gradio.components as components
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | File &amp;#34;/opt/conda/lib/python3.10/site-packages/gradio/components/__init__.py&amp;#34;, line 3, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | from gradio.components.bar_plot import BarPlot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | File &amp;#34;/opt/conda/lib/python3.10/site-packages/gradio/components/bar_plot.py&amp;#34;, line 7, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | import altair as alt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | File &amp;#34;/opt/conda/lib/python3.10/site-packages/altair/__init__.py&amp;#34;, line 649, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | from altair.vegalite import *
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | File &amp;#34;/opt/conda/lib/python3.10/site-packages/altair/vegalite/__init__.py&amp;#34;, line 2, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | from .v5 import *
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | File &amp;#34;/opt/conda/lib/python3.10/site-packages/altair/vegalite/v5/__init__.py&amp;#34;, line 2, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | from altair.expr.core import datum
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | File &amp;#34;/opt/conda/lib/python3.10/site-packages/altair/expr/__init__.py&amp;#34;, line 11, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | from altair.expr.core import ConstExpression, FunctionExpression
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | File &amp;#34;/opt/conda/lib/python3.10/site-packages/altair/expr/core.py&amp;#34;, line 6, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | from altair.utils import SchemaBase
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | File &amp;#34;/opt/conda/lib/python3.10/site-packages/altair/utils/__init__.py&amp;#34;, line 14, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | from .plugin_registry import PluginRegistry
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | File &amp;#34;/opt/conda/lib/python3.10/site-packages/altair/utils/plugin_registry.py&amp;#34;, line 13, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | from typing_extensions import TypeIs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;auto-cpu_1 | ImportError: cannot import name &amp;#39;TypeIs&amp;#39; from &amp;#39;typing_extensions&amp;#39; (/opt/conda/lib/python3.10/site-packages/typing_extensions.py)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これについては現時点でのバグっぽいですが、以下に回避策がありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/AbdBarho/stable-diffusion-webui-docker/issues/729" target="_blank" rel="noopener"
 &gt;https://github.com/AbdBarho/stable-diffusion-webui-docker/issues/729&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これで上手くいき、http://localhost:7860/ にアクセスすれば使用できました。&lt;/p&gt;
&lt;h2 id="sdxlモデルの設定"&gt;&lt;a href="#sdxl%e3%83%a2%e3%83%87%e3%83%ab%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;SDXLモデルの設定
&lt;/h2&gt;&lt;p&gt;SDXL モデルの設定については以下が参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://soroban.highreso.jp/article/article-042#651d4816a6d63105f25c3c7e-1aca58d91345337803792bb7" target="_blank" rel="noopener"
 &gt;https://soroban.highreso.jp/article/article-042#651d4816a6d63105f25c3c7e-1aca58d91345337803792bb7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ただ、モデルと VAE の配置場所は現在のバージョンだと少し異なるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;モデル: &lt;code&gt;data/models/Stable-diffusion&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;VAE: &lt;code&gt;data/models/VAE&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;p&gt;^ &lt;a class="link" href="https://soroban.highreso.jp/article/article-042#651d4816a6d63105f25c3c7e-1aca58d91345337803792bb7" target="_blank" rel="noopener"
 &gt;https://soroban.highreso.jp/article/article-042#651d4816a6d63105f25c3c7e-1aca58d91345337803792bb7&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://highreso.jp/edgehub/stablediffusion/vae.html#index_id8" target="_blank" rel="noopener"
 &gt;https://highreso.jp/edgehub/stablediffusion/vae.html#index_id8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://e-penguiner.com/stable-diffusion-webui-docker/" target="_blank" rel="noopener"
 &gt;https://e-penguiner.com/stable-diffusion-webui-docker/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://note.com/npaka/n/nc8b0e9a91d97" target="_blank" rel="noopener"
 &gt;https://note.com/npaka/n/nc8b0e9a91d97&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://zenn.dev/karaage0703/articles/bf86fe4946417b" target="_blank" rel="noopener"
 &gt;https://zenn.dev/karaage0703/articles/bf86fe4946417b&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://pc.watch.impress.co.jp/docs/column/nishikawa/1485422.html" target="_blank" rel="noopener"
 &gt;https://pc.watch.impress.co.jp/docs/column/nishikawa/1485422.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>asciidoctor-pdf で見出し前の改ページを無効にする</title><link>https://blog.ponkotools.com/posts/2024/09/30/asciidoctor-pdf/</link><pubDate>Mon, 30 Sep 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/09/30/asciidoctor-pdf/</guid><description>&lt;p&gt;asciidoctor-pdf で PDF を作成したときに、見出しレベル２の前に改ページが自動挿入されて無駄に余白があるページがあったので、これを無効化する方法です。&lt;/p&gt;
&lt;p&gt;PDF 作成時に指定するテーマファイルで設定します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.asciidoctor.org/pdf-converter/latest/theme/heading/#chapter" target="_blank" rel="noopener"
 &gt;https://docs.asciidoctor.org/pdf-converter/latest/theme/heading/#chapter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これを踏まえ、&lt;code&gt;heading-chapter&lt;/code&gt; で &lt;code&gt;break-before&lt;/code&gt; を &lt;code&gt;auto&lt;/code&gt; に指定すれば改ページが無効になりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;heading:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; chapter:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; break-before: auto
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ただ、&lt;code&gt;auto&lt;/code&gt; なので、場合によっては改ページされる場合もあるかもしれません。&lt;/p&gt;
&lt;p&gt;尚、上記の設定は &lt;code&gt;doctype&lt;/code&gt; が &lt;code&gt;book&lt;/code&gt; の場合のみ有効なようです。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.asciidoctor.org/pdf-converter/latest/theme/heading/#chapter" target="_blank" rel="noopener"
 &gt;https://docs.asciidoctor.org/pdf-converter/latest/theme/heading/#chapter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Asciidoc で include ディレクティブを使用している場合の画像へのパス</title><link>https://blog.ponkotools.com/posts/2024/09/26/asciidoc/</link><pubDate>Thu, 26 Sep 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/09/26/asciidoc/</guid><description>&lt;p&gt;画像を読み込んでいるファイルを、別の階層にあるファイルから &lt;code&gt;include&lt;/code&gt; ディレクティブで読み込むと、相対パスの位置が変わってしまいます。&lt;/p&gt;
&lt;p&gt;画像を読み込んでいるファイルを単体で表示したときにはそのファイルからの相対パスになりますが、&lt;code&gt;include&lt;/code&gt; しているファイルを表示したときには、&lt;code&gt;include&lt;/code&gt; しているファイルからの相対パスになってしまいます。&lt;/p&gt;
&lt;p&gt;同様のことで悩んでいる方はそれなりにいるようで、実際私もかなり困っています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/hyt126/items/7a070bc2b1e185b9146f" target="_blank" rel="noopener"
 &gt;https://qiita.com/hyt126/items/7a070bc2b1e185b9146f&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/ihgs/items/3c7a4fa9a2a81b23da82" target="_blank" rel="noopener"
 &gt;https://qiita.com/ihgs/items/3c7a4fa9a2a81b23da82&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://discuss.asciidoctor.org/Strange-issues-with-asciidoc-imagesdir-stops-working-td8194.html" target="_blank" rel="noopener"
 &gt;https://discuss.asciidoctor.org/Strange-issues-with-asciidoc-imagesdir-stops-working-td8194.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;とりあえずの解決方法としては、私にとっては以下の方法が一番役に立ちました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/75919047/images-in-various-locations-in-included-asciidoc-files" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/75919047/images-in-various-locations-in-included-asciidoc-files&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ちょっと手間ですが、&lt;code&gt;include&lt;/code&gt; 直前で &lt;code&gt;imagedir&lt;/code&gt; を都度セットします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;:imagesdir: hoge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;include::hoge/included_file.adoc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ただし、多重で include している場合は上記では上手くいきません。&lt;br&gt;
この場合は、試行錯誤の結果、以下のようにすることで上手くいきました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ifdef::imagesdir[:imagesdir: {imagesdir}/hoge]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ifndef::imagesdir[:imagesdir: hoge]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;include::hoge/included_file.adoc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;imagesdir&lt;/code&gt; が既に定義されている（＝別のファイルから include されている）場合は、現在の &lt;code&gt;imagesdir&lt;/code&gt; に付加する形で &lt;code&gt;imagesdir&lt;/code&gt; を再定義します。&lt;br&gt;
&lt;code&gt;imagesdir&lt;/code&gt; が定義されていない（＝別のファイルから include されていない）場合は、前述と同じように &lt;code&gt;imagesdir&lt;/code&gt; を定義します。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/75919047/images-in-various-locations-in-included-asciidoc-files" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/75919047/images-in-various-locations-in-included-asciidoc-files&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Jekyll で Asciidoc を使用する</title><link>https://blog.ponkotools.com/posts/2024/09/12/jekyll-asciidoc/</link><pubDate>Thu, 12 Sep 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/09/12/jekyll-asciidoc/</guid><description>&lt;p&gt;markdown だけでなく asciidoc も使えたら便利なので。&lt;/p&gt;
&lt;p&gt;以下の記事で作成した環境に対して asciidoc を使えるようにします。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2024/09/jekyll-docker.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2024/09/jekyll-docker.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;調べたところ以下のプラグインを使えば出来そうだったので、これを使ってみます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/asciidoctor/jekyll-asciidoc" target="_blank" rel="noopener"
 &gt;https://github.com/asciidoctor/jekyll-asciidoc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="gemfile-の変更"&gt;&lt;a href="#gemfile-%e3%81%ae%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;Gemfile の変更
&lt;/h2&gt;&lt;p&gt;ドキュメントの通りに、&lt;code&gt;Gemfile&lt;/code&gt; に以下を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;group :jekyll_plugins do
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; gem &amp;#39;jekyll-asciidoc&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;end
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;_config.yml&lt;/code&gt; に以下を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;plugins:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - jekyll-asciidoc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;尚、&lt;code&gt;jekyll-asciidoc&lt;/code&gt; は他のプラグインより先に記述する必要があるそうです。&lt;br&gt;
詳細は以下を参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/asciidoctor/jekyll-asciidoc?tab=readme-ov-file#plugin-ordering" target="_blank" rel="noopener"
 &gt;https://github.com/asciidoctor/jekyll-asciidoc?tab=readme-ov-file#plugin-ordering&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これで、&lt;code&gt;_post&lt;/code&gt; フォルダ内に asciidoc で書いたドキュメントを追加すれば OK です。&lt;br&gt;
ファイル名は Jekyll の決まりとして、&lt;code&gt;YYYY-MM-DD-title.adoc&lt;/code&gt; のように日付が入っている必要があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://jekyllrb-ja.github.io/docs/posts/" target="_blank" rel="noopener"
 &gt;https://jekyllrb-ja.github.io/docs/posts/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下、サンプル通りに記事を作成してみました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;= Sample Page
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;:page-layout: post
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;:page-permalink: /sample/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;:url-asciidoctor: https://asciidoctor.org
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;This is a sample page composed in AsciiDoc.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Jekyll converts it to HTML using {url-asciidoctor}[Asciidoctor].
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[source,ruby]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;puts &amp;#34;Hello, World!&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ただし、&lt;code&gt;layuout&lt;/code&gt; は &lt;code&gt;post&lt;/code&gt; に変更しています。&lt;br&gt;
レイアウトについては以下。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/a999/items/6c29ce072c19448ea579" target="_blank" rel="noopener"
 &gt;https://qiita.com/a999/items/6c29ce072c19448ea579&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これできちんと表示されることを確認しました。&lt;/p&gt;
&lt;h2 id="include-ディレクティブを使用するときの相対パス"&gt;&lt;a href="#include-%e3%83%87%e3%82%a3%e3%83%ac%e3%82%af%e3%83%86%e3%82%a3%e3%83%96%e3%82%92%e4%bd%bf%e7%94%a8%e3%81%99%e3%82%8b%e3%81%a8%e3%81%8d%e3%81%ae%e7%9b%b8%e5%af%be%e3%83%91%e3%82%b9" class="header-anchor"&gt;&lt;/a&gt;include ディレクティブを使用するときの相対パス
&lt;/h2&gt;&lt;p&gt;asciidoc では &lt;code&gt;include&lt;/code&gt; ディレクティブを使用して他の asciidoc ファイルを読み込むことができますが、このままやっても上手く描画されませんでした。&lt;br&gt;
同様の内容が issue に挙がっていました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/asciidoctor/jekyll-asciidoc/issues/182" target="_blank" rel="noopener"
 &gt;https://github.com/asciidoctor/jekyll-asciidoc/issues/182&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ベースディレクトリの設定がデフォルトではプロジェクトルートになっているので、ソースディレクトリとなるように設定すれば良さそうです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/asciidoctor/jekyll-asciidoc?tab=readme-ov-file#specifying-the-base-directory" target="_blank" rel="noopener"
 &gt;https://github.com/asciidoctor/jekyll-asciidoc?tab=readme-ov-file#specifying-the-base-directory&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;_config.yml&lt;/code&gt; に以下を追記すれば上手くいきました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;asciidoctor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;base_dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="l"&gt;docdir&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;safe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/asciidoctor/jekyll-asciidoc" target="_blank" rel="noopener"
 &gt;https://github.com/asciidoctor/jekyll-asciidoc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/a999/items/6c29ce072c19448ea579" target="_blank" rel="noopener"
 &gt;https://qiita.com/a999/items/6c29ce072c19448ea579&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/asciidoctor/jekyll-asciidoc/issues/182" target="_blank" rel="noopener"
 &gt;https://github.com/asciidoctor/jekyll-asciidoc/issues/182&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Jekyll + Docker で静的サイトを作成する</title><link>https://blog.ponkotools.com/posts/2024/09/11/jekyll-docker/</link><pubDate>Wed, 11 Sep 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/09/11/jekyll-docker/</guid><description>&lt;p&gt;一番基本的なところを試してみたかっただけなのですが、嵌ったのでメモしておきます。&lt;/p&gt;
&lt;p&gt;公式の Docker イメージは以下のようなのでこれを使いますが、長い間メンテナンスされていないようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/r/jekyll/jekyll/" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/r/jekyll/jekyll/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;docker 24.0.7&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="新規作成"&gt;&lt;a href="#%e6%96%b0%e8%a6%8f%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;新規作成
&lt;/h2&gt;&lt;p&gt;まずはドキュメントに従って、以下のコマンドでブログを新規作成してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;site_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-blog&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run --rm &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --volume&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;:/srv/jekyll&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -it jekyll/jekyll &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sh -c &lt;span class="s2"&gt;&amp;#34;chown -R jekyll /usr/gem/ &amp;amp;&amp;amp; jekyll new &lt;/span&gt;&lt;span class="nv"&gt;$site_name&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$site_name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下のエラーが出て失敗します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/usr/local/lib/ruby/3.1.0/fileutils.rb:243:in `mkdir&amp;#39;: Permission denied @ dir_s_mkdir - /srv/jekyll/my-blog (Errno::EACCES)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでかなり嵌ったのですが、以下の記事を見つけました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/57503011/unable-to-build-cloned-jekyll-site-jekyll-3-8-5-error-permission-denied-d" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/57503011/unable-to-build-cloned-jekyll-site-jekyll-3-8-5-error-permission-denied-d&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;どうやら環境変数を指定すればいいそうです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;site_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-blog&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;JEKYLL_UID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;JEKYLL_GID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;$PWD:/srv/jekyll&amp;#34;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;jekyll&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;jekyll&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;chown -R jekyll /usr/gem/ &amp;amp;&amp;amp; jekyll new $site_name&amp;#34;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;site_name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで、&lt;code&gt;my-blog&lt;/code&gt; というフォルダが作成され、中に Jekyll のブログの雛形が作成されています。&lt;/p&gt;
&lt;h2 id="ビルド"&gt;&lt;a href="#%e3%83%93%e3%83%ab%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;ビルド
&lt;/h2&gt;&lt;p&gt;上記で作成した内容をビルドして静的サイトを生成します。&lt;br&gt;
引き続き、環境変数を指定したうえでドキュメント通りに以下を実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;site_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-blog&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;JEKYLL_UID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;JEKYLL_GID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;$PWD/$site_name:/srv/jekyll&amp;#34;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;jekyll&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;jekyll&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;jekyll&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;my-blog&lt;/code&gt; の中に &lt;code&gt;_site&lt;/code&gt; というフォルダが出力されました。&lt;/p&gt;
&lt;h2 id="サーバー起動"&gt;&lt;a href="#%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;サーバー起動
&lt;/h2&gt;&lt;p&gt;次はサーバーを起動してブラウザからアクセスしてみます。&lt;br&gt;
こちらも引き続き、環境変数を指定したうえでドキュメント通りに以下を実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;site_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-blog&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;JEKYLL_UID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;JEKYLL_GID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;$PWD/$site_name:/srv/jekyll&amp;#34;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4000&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;jekyll&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;jekyll&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;jekyll&lt;/span&gt; &lt;span class="n"&gt;serve&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;force_polling&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;livereload&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下のエラーが出ました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;internal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;site_ruby&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;3.1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rubygems&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;core_ext&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;kernel_require&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rb&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;: cannot load such file -- webrick (LoadError)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;webrick がないそうなので、&lt;code&gt;my-blog&lt;/code&gt; 内の &lt;code&gt;Gemfile&lt;/code&gt; に以下を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gem &amp;#34;webrick&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで上記のコマンドを実行すれば無事サーバーが起動し、&lt;code&gt;http://localhost:4000&lt;/code&gt; にアクセスすることで閲覧できました。&lt;/p&gt;
&lt;h2 id="所感"&gt;&lt;a href="#%e6%89%80%e6%84%9f" class="header-anchor"&gt;&lt;/a&gt;所感
&lt;/h2&gt;&lt;p&gt;公式の Docker イメージ使って基本的なことを確認したかっただけなのに全然動かねぇじゃんって思いました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/57503011/unable-to-build-cloned-jekyll-site-jekyll-3-8-5-error-permission-denied-d" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/57503011/unable-to-build-cloned-jekyll-site-jekyll-3-8-5-error-permission-denied-d&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>asciidoctor-pdf で admonition のアイコンを別の画像に差し替える</title><link>https://blog.ponkotools.com/posts/2024/09/09/asciidoctor-pdf/</link><pubDate>Mon, 09 Sep 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/09/09/asciidoctor-pdf/</guid><description>&lt;p&gt;アイコン画像を別で用意して、それに差し替える方法です。&lt;/p&gt;
&lt;p&gt;ドキュメント内で以下のように記述して、アイコンを画像ベースの設定に変更します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;:icons: image
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そのうえで、PDF 作成用のテーマファイルで以下のように画像を指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;admonition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;note&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# NOTEのアイコン画像のパスを指定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;caution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# CAUTIONのアイコン画像のパスを指定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.asciidoctor.org/asciidoc/latest/macros/icons-image/" target="_blank" rel="noopener"
 &gt;https://docs.asciidoctor.org/asciidoc/latest/macros/icons-image/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.asciidoctor.org/pdf-converter/latest/theme/admonition/" target="_blank" rel="noopener"
 &gt;https://docs.asciidoctor.org/pdf-converter/latest/theme/admonition/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide] Windows で実行するとオーバーフローエラーが発生</title><link>https://blog.ponkotools.com/posts/2024/08/30/pyside/</link><pubDate>Fri, 30 Aug 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/08/30/pyside/</guid><description>&lt;p&gt;PySide6 で作成したアプリを Pyinstaller で exe 化して実行すると、オーバーフローのエラーが発生しました。&lt;/p&gt;
&lt;p&gt;エラーの内容は以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;OverflowError: Python int too large to convert to C long
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;該当箇所のコードは、以下のように &lt;code&gt;QLineChart&lt;/code&gt; を使ってグラフを作成している箇所でした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;series&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QLineSeries&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 省略...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;qdt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QDateTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;qdt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setSecsSinceEpoch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qdt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toMSecsSinceEpoch&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;toMSecsSinceEpoch()&lt;/code&gt; はエポックタイムをミリ秒で返す関数です。&lt;br&gt;
これを &lt;code&gt;append&lt;/code&gt; 関数に渡すと、32bit の範囲を超えているとしてエラーが発生していました。&lt;/p&gt;
&lt;p&gt;ビルド環境も実行環境も 64bit なのに、何故 32bit の &lt;code&gt;long int&lt;/code&gt; として扱われているのか？&lt;br&gt;
調べてみたところ、以下の記事に辿り着きました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/72568201/why-overflowerror-occured-only-on-pyside6" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/72568201/why-overflowerror-occured-only-on-pyside6&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;どうやら &lt;code&gt;float&lt;/code&gt; でキャストすれば良さそうということで、以下のように修正したところ、正常に動作するようになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qdt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toMSecsSinceEpoch&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/72568201/why-overflowerror-occured-only-on-pyside6" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/72568201/why-overflowerror-occured-only-on-pyside6&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[python] pipenv で無関係のパッケージが勝手にアップデートされる</title><link>https://blog.ponkotools.com/posts/2024/07/17/python/</link><pubDate>Wed, 17 Jul 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/07/17/python/</guid><description>&lt;p&gt;pipenv でパッケージをインストールしたときに、全く関係ないパッケージが勝手にアップデートされて困ったことがありました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--keep-outdated&lt;/code&gt; を付与すればいいという情報もありますが、現在の pipenv ではこのオプションは削除されています。&lt;/p&gt;
&lt;p&gt;とりあえず以下のようにして回避しました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. &lt;code&gt;Pipfile&lt;/code&gt; 内の全てのパッケージのバージョンを指定&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Pipfile&lt;/code&gt; をエディタで開き、でバージョンを指定していなかったパッケージに全てバージョンを記入しました。&lt;br&gt;
バージョンは、&lt;code&gt;Pipfile.lock&lt;/code&gt; を参照して、現在インストールされているバージョンを記入しました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. すべてのパッケージをアンインストール&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pipenv uninstall --all
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;3. &lt;code&gt;Pipfile.lock&lt;/code&gt; を削除&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ rm Pipfile.lock
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;4. 新しい依存関係をインストール&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pipenv install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;</description></item><item><title>Shotcut でフリーズフレームを入れる</title><link>https://blog.ponkotools.com/posts/2024/07/06/shotcut/</link><pubDate>Sat, 06 Jul 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/07/06/shotcut/</guid><description>&lt;p&gt;動画編集ソフトの Shotcut にはフレーズフレーム機能はありませんが、以下のようにすることで簡単にフリーズフレームを入れることができます。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Shotcut 24.06.26&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;図中の動画は以下のサイトから適当にダウンロードしてきました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://pixabay.com/ja/" target="_blank" rel="noopener"
 &gt;https://pixabay.com/ja/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やり方"&gt;&lt;a href="#%e3%82%84%e3%82%8a%e6%96%b9" class="header-anchor"&gt;&lt;/a&gt;やり方
&lt;/h2&gt;&lt;p&gt;フリーズフレームを入れたい場所に再生ヘッドを移動し、「再生ヘッドで分割する」を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="394px" data-flex-grow="164" height="1192" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2024/07/06/shotcut/01.webp" srcset="https://blog.ponkotools.com/posts/2024/07/06/shotcut/01_hu_13c47485009a3bb9.webp 800w, https://blog.ponkotools.com/posts/2024/07/06/shotcut/01_hu_13b5569e1b3d2054.webp 1600w, https://blog.ponkotools.com/posts/2024/07/06/shotcut/01.webp 1959w" width="1959"&gt;&lt;/p&gt;
&lt;p&gt;「ファイル &amp;gt; 書き出し &amp;gt; フレーム」で、フレームを静止画としてエクスポートします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="394px" data-flex-grow="164" height="1192" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2024/07/06/shotcut/02.webp" srcset="https://blog.ponkotools.com/posts/2024/07/06/shotcut/02_hu_5bb43a42897a0304.webp 800w, https://blog.ponkotools.com/posts/2024/07/06/shotcut/02_hu_260ae78f37f07176.webp 1600w, https://blog.ponkotools.com/posts/2024/07/06/shotcut/02.webp 1959w" width="1959"&gt;&lt;/p&gt;
&lt;p&gt;エクスポートした静止画を取り込み、それを分割した動画の間に挿入します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="394px" data-flex-grow="164" height="1192" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2024/07/06/shotcut/03.webp" srcset="https://blog.ponkotools.com/posts/2024/07/06/shotcut/03_hu_583c6a7187ad788f.webp 800w, https://blog.ponkotools.com/posts/2024/07/06/shotcut/03_hu_acd59012dd79302.webp 1600w, https://blog.ponkotools.com/posts/2024/07/06/shotcut/03.webp 1959w" width="1959"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="394px" data-flex-grow="164" height="1192" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2024/07/06/shotcut/04.webp" srcset="https://blog.ponkotools.com/posts/2024/07/06/shotcut/04_hu_5e94c474bed7aabe.webp 800w, https://blog.ponkotools.com/posts/2024/07/06/shotcut/04_hu_5432112a7badea80.webp 1600w, https://blog.ponkotools.com/posts/2024/07/06/shotcut/04.webp 1959w" width="1959"&gt;&lt;/p&gt;
&lt;p&gt;あとは、挿入した静止画を選択し、右クリックして「プロパティ」を開き、長さを変更します。&lt;/p&gt;</description></item><item><title>redis コンテナでの redis-server の起動方法による違い</title><link>https://blog.ponkotools.com/posts/2024/06/27/redis/</link><pubDate>Thu, 27 Jun 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/06/27/redis/</guid><description>&lt;p&gt;redis の公式のイメージを docker compose で動かしていたのですが、&lt;code&gt;command&lt;/code&gt; を指定しない場合のデフォルトの実行コマンドは &lt;code&gt;redis-server&lt;/code&gt; で、この場合、コンテナを再起動してもデータが残っていました。&lt;/p&gt;
&lt;p&gt;しかし、コマンドを &lt;code&gt;command: sh -c &amp;quot;redis-server&amp;quot;&lt;/code&gt; としたところ、コンテナ再起動でデータがクリアされたので、両者の違いについて ChatGPT に聞いてみました。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;command: &amp;quot;redis-server&amp;quot;:&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;この設定では、単純に redis-server コマンドが実行されます。Docker はこのコマンドを直接実行し、Redis サーバーが起動します。この場合、Redis サーバーが直接起動されるため、Redis のデフォルトの動作が適用され、データが残ります。再起動してもデータがクリアされないのは、Redis サーバーが正しく起動し、データをインメモリに保持しているためです。&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;code&gt;command: sh -c &amp;quot;redis-server&amp;quot;:&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;一方、この設定では、sh -c コマンドを使用してシェルでコマンドを実行します。sh -c コマンドは、指定されたコマンドをシェル経由で実行します。この場合、redis-server コマンドがシェル経由で実行されるため、Docker はシェルプロセスを起動し、そのシェルプロセスが redis-server コマンドを実行します。この場合、シェルプロセスがメインプロセスとなり、redis-server がそのサブプロセスとして実行されます。そのため、正しくプロセスが管理されない可能性があり、コンテナの再起動時にデータがクリアされる可能性があります。&lt;/p&gt;</description></item><item><title>[PySide] qasync を使って非同期処理をバックグランドで行う</title><link>https://blog.ponkotools.com/posts/2024/04/22/pyside/</link><pubDate>Mon, 22 Apr 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/04/22/pyside/</guid><description>&lt;p&gt;PySide6 で GUI アプリを作成している中で、I/O バウンドな処理の完了を待っていると GUI が固まりました。&lt;/p&gt;
&lt;p&gt;通常、バックグラウンドで何か処理を行う際に GUI の処理を止めないようにするために、QThread などを使って別スレッドで処理を行いつつ GUI スレッドを回したりします。&lt;br&gt;
今回もそうやって作っていたのですが、完了までに時間のかかる I/O バウンドな処理を行わせたい場合、上手くいかない場合がありました。
I/O バウンドな処理なので、ayncio を使って非同期処理にしてやればいいと思ったのですが、Qt のイベントループと asyncio を適切に統合する必要があるようで、どのように記述すればいいのかいまいち分かりませんでした。&lt;/p&gt;
&lt;p&gt;そんな中、&lt;code&gt;qasync&lt;/code&gt; というライブラリを使えば、とても簡単に処理を組み込むことができました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/CabbageDevelopment/qasync" target="_blank" rel="noopener"
 &gt;https://github.com/CabbageDevelopment/qasync&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;コードの記述も、QThread を使う場合に比べシンプルでスッキリします。&lt;/p&gt;
&lt;p&gt;ちなみに、&lt;code&gt;asyncqt&lt;/code&gt; というライブラリもありますが、こちらは既にメンテナンスされていないようです。
&lt;code&gt;qasync&lt;/code&gt; は &lt;code&gt;asyncqt&lt;/code&gt; のフォークで、現在でもメンテナンスされているようなので、使うなら &lt;code&gt;qasync&lt;/code&gt; のほうが良いと思います。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;python 3.11&lt;/li&gt;
&lt;li&gt;pyside6 6.6.3.1&lt;/li&gt;
&lt;li&gt;qasync 0.27.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtWidgets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QMainWindow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QLabel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;qasync&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QEventLoop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;asyncSlot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QMainWindow&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setWindowTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;qasync sample&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Press the button.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Start&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clicked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on_button_clicked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCentralWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@asyncSlot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_button_clicked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;waiting...&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# I/O バウンドな処理を想定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Press the button.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QEventLoop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_event_loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/CabbageDevelopment/qasync" target="_blank" rel="noopener"
 &gt;https://github.com/CabbageDevelopment/qasync&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Ubuntu のユーザー名を変更する</title><link>https://blog.ponkotools.com/posts/2024/04/02/ubuntu/</link><pubDate>Tue, 02 Apr 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/04/02/ubuntu/</guid><description>&lt;p&gt;Ubuntu 20.04 で確認しました。&lt;/p&gt;
&lt;h2 id="新しいユーザーを作成する"&gt;&lt;a href="#%e6%96%b0%e3%81%97%e3%81%84%e3%83%a6%e3%83%bc%e3%82%b6%e3%83%bc%e3%82%92%e4%bd%9c%e6%88%90%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;新しいユーザーを作成する
&lt;/h2&gt;&lt;p&gt;ログインユーザー自身のユーザー名は変更できないので、一時的に管理者権限を持ったユーザーを作成します。&lt;/p&gt;
&lt;p&gt;Ubuntu の場合は以下のように GUI で簡単に追加できます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;設定 &amp;gt; ユーザー &amp;gt; ユーザーを追加&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ユーザー名とグループ名の変更"&gt;&lt;a href="#%e3%83%a6%e3%83%bc%e3%82%b6%e3%83%bc%e5%90%8d%e3%81%a8%e3%82%b0%e3%83%ab%e3%83%bc%e3%83%97%e5%90%8d%e3%81%ae%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;ユーザー名とグループ名の変更
&lt;/h2&gt;&lt;p&gt;作成した新しいユーザーでログインして行います。&lt;/p&gt;
&lt;h3 id="ユーザー名の変更"&gt;&lt;a href="#%e3%83%a6%e3%83%bc%e3%82%b6%e3%83%bc%e5%90%8d%e3%81%ae%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;ユーザー名の変更
&lt;/h3&gt;&lt;p&gt;以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo usermod -l new_username -d /home/new_username -m old_username
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;尚、&lt;code&gt;usermod&lt;/code&gt; コマンドの &lt;code&gt;-g&lt;/code&gt; オプションでグループ名も一緒に変更できるような記述も見つけましたが、私の場合、&lt;code&gt;usermod: グループ 'new_username' は存在しません&lt;/code&gt; のエラーが表示されてできなかったため、ユーザー名とグループ名の変更を分けて行いました。&lt;/p&gt;
&lt;h3 id="グループ名の変更"&gt;&lt;a href="#%e3%82%b0%e3%83%ab%e3%83%bc%e3%83%97%e5%90%8d%e3%81%ae%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;グループ名の変更
&lt;/h3&gt;&lt;p&gt;以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo groupmod -n new_username old_username
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以上で、変更後のユーザーでログインして問題なく使えることを確認しました。&lt;br&gt;
ただ、唯一、ユーザーのアイコン画像だけがクリアされていました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://zenn.dev/creationup2u/articles/1d863f40fec16a" target="_blank" rel="noopener"
 &gt;https://zenn.dev/creationup2u/articles/1d863f40fec16a&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://minory.org/linux-usermod.html" target="_blank" rel="noopener"
 &gt;https://minory.org/linux-usermod.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] Python の Windows コンテナを動かしてみた</title><link>https://blog.ponkotools.com/posts/2024/03/18/docker-python/</link><pubDate>Mon, 18 Mar 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/03/18/docker-python/</guid><description>&lt;p&gt;ホストもコンテナも Windows になるので、Dockerfile の記述方法や、コンテナ起動時のオプションの指定方法なども Linux とは異なります。&lt;/p&gt;
&lt;p&gt;Windows 上で Docker を (Docker Desktop を使わずに) 動かす方法については以下を参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2023/11/docker-windows.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2023/11/docker-windows.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そのうえで、今回 Python の Windows コンテナを動かしてみました。&lt;/p&gt;
&lt;p&gt;Docker Hub にある Python の Windows コンテナとしては、&lt;code&gt;windowsservercore-ltsc2022&lt;/code&gt; と &lt;code&gt;windowsservercore-1809&lt;/code&gt; があるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/_/python" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/_/python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回は &lt;code&gt;python:3.11-windowsservercore-1809&lt;/code&gt; のイメージを使いました。&lt;/p&gt;
&lt;h2 id="dockerfile-のサンプル"&gt;&lt;a href="#dockerfile-%e3%81%ae%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;Dockerfile のサンプル
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;FROM python:3.11-windowsservercore-1809
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CMD &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cmd.exe&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Linux コンテナでは &lt;code&gt;CMD [ &amp;quot;/bin/bash&amp;quot; ]&lt;/code&gt; のように記述していましたが、Windows コンテナでは &lt;code&gt;CMD [&amp;quot;cmd.exe&amp;quot;]&lt;/code&gt; または &lt;code&gt;CMD [&amp;quot;powershell.exe&amp;quot;]&lt;/code&gt; のように記述します。&lt;/p&gt;
&lt;h2 id="コンテナ起動例"&gt;&lt;a href="#%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e8%b5%b7%e5%8b%95%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;コンテナ起動例
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; docker run -it --rm ^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --name コンテナ名 ^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v %CD%&lt;span class="se"&gt;\w&lt;/span&gt;orkspace:C:&lt;span class="se"&gt;\w&lt;/span&gt;orkspace ^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --workdir&lt;span class="o"&gt;=&lt;/span&gt;C:&lt;span class="se"&gt;\w&lt;/span&gt;orkspace ^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; イメージ名
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Linux ではカレントディレクトリを指定するために &lt;code&gt;$(pwd)&lt;/code&gt; と記述したりしていましたが、Windows なので &lt;code&gt;%CD%&lt;/code&gt; と記述します。&lt;br&gt;
パスの区切りは &lt;code&gt;\(バックスラッシュ)&lt;/code&gt; になります。&lt;br&gt;
コマンド途中での改行も、Linux ではバックスラッシュでしたが、Windows なので &lt;code&gt;^&lt;/code&gt; になります。&lt;br&gt;
また、Windows コンテナなので、マウント先のパスも C ドライブからのパスで記述します。&lt;/p&gt;
&lt;p&gt;とりあえずここまで。&lt;br&gt;
追々いろいろ追記するかもしれません。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/ishibashi-futoshi/items/db807d64624f43be1be9" target="_blank" rel="noopener"
 &gt;https://qiita.com/ishibashi-futoshi/items/db807d64624f43be1be9&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>YOLOv8 を動かそうとしたら ImportError: libGL.so.1: cannot open shared object file: No such file or directory のエラーが出た</title><link>https://blog.ponkotools.com/posts/2024/02/28/yolov8/</link><pubDate>Wed, 28 Feb 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/02/28/yolov8/</guid><description>&lt;p&gt;python で YOLOv8 を動かそうとしたら以下のエラーが出ました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from ultralytics import YOLO
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Traceback (most recent call last):
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/workspace/yolov8/test1.py&amp;#34;, line 1, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; from ultralytics import YOLO
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/usr/local/lib/python3.11/site-packages/ultralytics/__init__.py&amp;#34;, line 5, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; from ultralytics.data.explorer.explorer import Explorer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/usr/local/lib/python3.11/site-packages/ultralytics/data/__init__.py&amp;#34;, line 3, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; from .base import BaseDataset
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/usr/local/lib/python3.11/site-packages/ultralytics/data/base.py&amp;#34;, line 12, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; import cv2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/usr/local/lib/python3.11/site-packages/cv2/__init__.py&amp;#34;, line 181, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; bootstrap()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/usr/local/lib/python3.11/site-packages/cv2/__init__.py&amp;#34;, line 153, in bootstrap
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; native_module = importlib.import_module(&amp;#34;cv2&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/usr/local/lib/python3.11/importlib/__init__.py&amp;#34;, line 126, in import_module
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; return _bootstrap._gcd_import(name[level:], package, level)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ImportError: libGL.so.1: cannot open shared object file: No such file or directory
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このエラーは、OpenCV が GPU の OpenGL ライブラリを見つけられないことが原因で起きているエラーのようです。&lt;/p&gt;
&lt;p&gt;YOLOv8 (ultralytics) をインストールすると依存関係にある OpenCV もインストールされるようですが、以下のページによれば、検出結果の可視化などを行ったりする場合のみ OpenCV が必要で、他のコア機能は OpenCV に依存しないとあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/ultralytics/ultralytics/issues/2179" target="_blank" rel="noopener"
 &gt;https://github.com/ultralytics/ultralytics/issues/2179&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/ultralytics/ultralytics/pull/3480" target="_blank" rel="noopener"
 &gt;https://github.com/ultralytics/ultralytics/pull/3480&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;しかし、私の場合、検出結果の可視化とか何もしていない、というかそもそも最初の import 文のところでエラーになってしまっています。&lt;/p&gt;
&lt;p&gt;尚、&lt;code&gt;opencv-python&lt;/code&gt; ではなく、&lt;code&gt;opencv-python-headless&lt;/code&gt; をインストールすれば解決できる場合もあるそうですが、私の場合、それでも上記のエラーが発生しました。&lt;/p&gt;
&lt;p&gt;仕方がないので、OpenGL のライブラリをインストールして解決しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install -y libgl1-mesa-glx libglib2.0-0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://zenn.dev/techmadot/articles/opengl4-on-wsl" target="_blank" rel="noopener"
 &gt;https://zenn.dev/techmadot/articles/opengl4-on-wsl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/ultralytics/ultralytics/tree/main" target="_blank" rel="noopener"
 &gt;https://github.com/ultralytics/ultralytics/tree/main&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.ultralytics.com/ja/quickstart/" target="_blank" rel="noopener"
 &gt;https://docs.ultralytics.com/ja/quickstart/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] Iris データセットを Pandas で読み込む</title><link>https://blog.ponkotools.com/posts/2024/02/21/python/</link><pubDate>Wed, 21 Feb 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/02/21/python/</guid><description>&lt;p&gt;機械学習のサンプルデータとしてよく使われるものの一つに Iris（アヤメ）のデータセットがあります。その読み込み方法です。&lt;/p&gt;
&lt;p&gt;Iris のデータセットを取得する方法自体はいくつかあるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://py-memo.com/python/load-iris/" target="_blank" rel="noopener"
 &gt;https://py-memo.com/python/load-iris/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回は Iris のデータは機械学習用の定番のライブラリである &lt;code&gt;scikit-learn&lt;/code&gt; を使いました。&lt;/p&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;pd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;sklearn.datasets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_iris&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;iris&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;load_iris&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;df_iris&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iris&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;iris&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;feature_names&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 目的変数である花の種類（target）のカラムを作成（花の種類を数値から文字列に変換して追加）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;df_iris&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;target&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;iris&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;target_names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;iris&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df_iris&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sepal length &lt;span class="o"&gt;(&lt;/span&gt;cm&lt;span class="o"&gt;)&lt;/span&gt; sepal width &lt;span class="o"&gt;(&lt;/span&gt;cm&lt;span class="o"&gt;)&lt;/span&gt; petal length &lt;span class="o"&gt;(&lt;/span&gt;cm&lt;span class="o"&gt;)&lt;/span&gt; petal width &lt;span class="o"&gt;(&lt;/span&gt;cm&lt;span class="o"&gt;)&lt;/span&gt; target
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;0&lt;/span&gt; 5.1 3.5 1.4 0.2 setosa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1&lt;/span&gt; 4.9 3.0 1.4 0.2 setosa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;2&lt;/span&gt; 4.7 3.2 1.3 0.2 setosa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;3&lt;/span&gt; 4.6 3.1 1.5 0.2 setosa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;4&lt;/span&gt; 5.0 3.6 1.4 0.2 setosa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.. ... ... ... ... ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;145&lt;/span&gt; 6.7 3.0 5.2 2.3 virginica
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;146&lt;/span&gt; 6.3 2.5 5.0 1.9 virginica
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;147&lt;/span&gt; 6.5 3.0 5.2 2.0 virginica
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;148&lt;/span&gt; 6.2 3.4 5.4 2.3 virginica
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;149&lt;/span&gt; 5.9 3.0 5.1 1.8 virginica
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;150&lt;/span&gt; rows x &lt;span class="m"&gt;5&lt;/span&gt; columns&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;load_iris&lt;/code&gt; 関数で呼び出されたデータセットは numpy 形式です。&lt;br&gt;
これを扱いやすいように Pandas でデータフレームに変換しています。&lt;br&gt;
また、&lt;code&gt;load_iris&lt;/code&gt; 関数では、説明変数は &lt;code&gt;iris.data&lt;/code&gt;、目的変数は &lt;code&gt;iris.target&lt;/code&gt; に実装されています。&lt;br&gt;
カラム名は &lt;code&gt;iris.feature_names&lt;/code&gt; に入っています。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;iris.target&lt;/code&gt; は花の種類を数値として保持しており、その数値に対応した花の名前は &lt;code&gt;iris.target_names&lt;/code&gt; に定義されています。&lt;br&gt;
花の種類をカラムに追加する際には文字列に変換して追加しています。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://py-memo.com/python/load-iris/" target="_blank" rel="noopener"
 &gt;https://py-memo.com/python/load-iris/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/ao_log/items/fe9bd42fd249c2a7ee7a" target="_blank" rel="noopener"
 &gt;https://qiita.com/ao_log/items/fe9bd42fd249c2a7ee7a&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://py-memo.com/python/load-iris/" target="_blank" rel="noopener"
 &gt;https://py-memo.com/python/load-iris/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://aiacademy.jp/texts/show/?id=90" target="_blank" rel="noopener"
 &gt;https://aiacademy.jp/texts/show/?id=90&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>WSL で使用しているディスクスペースを解放する</title><link>https://blog.ponkotools.com/posts/2024/02/20/wsl/</link><pubDate>Tue, 20 Feb 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/02/20/wsl/</guid><description>&lt;p&gt;WSL 上の Ubuntu で docker を使っていたのですが、ストレージの空き容量が少なくなってきたので docker イメージを削除しても空き容量が変化しませんでした。&lt;/p&gt;
&lt;p&gt;調べてみたところ、どうやら仮想ディスクの最適化まで行わないとディスクスペースは解放されないようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://01futabato10.hateblo.jp/entry/2022/12/02/095031" target="_blank" rel="noopener"
 &gt;https://01futabato10.hateblo.jp/entry/2022/12/02/095031&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/siruku6/items/c91a40d460095013540d" target="_blank" rel="noopener"
 &gt;https://qiita.com/siruku6/items/c91a40d460095013540d&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ただ、私の PC はストレージ容量が少なく、頻繁に Docker イメージを消して容量を確保しているため、都度コマンドを打つのは面倒ということで、スクリプト化しました。&lt;/p&gt;
&lt;p&gt;コマンドとしては、diskpart を使う方法と、Optimize-VHD を使う方法があるみたいですが、Optimize-VHD は Hyper-V を有効化する必要があり、Windows Home では使えないということで、今回は diskpart を使うことにしました。&lt;/p&gt;
&lt;p&gt;diskpart でスクリプトを実行する方法は以下に記載されています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/diskpart-scripts-and-examples" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/diskpart-scripts-and-examples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプル"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;サンプル
&lt;/h2&gt;&lt;p&gt;まずは diskpart で実行するスクリプトを作成します（ここでは &lt;code&gt;sample.txt&lt;/code&gt; としました）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;select vdisk file=&amp;#34;%USERPROFILE%\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu22.04LTS_79rhkp1fndgsc\LocalState\ext4.vhdx&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;attach vdisk readonly
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;compact vdisk
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;detach vdisk
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;file&lt;/code&gt; のパスは環境によって異なると思うので、以下を参考に調べてください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://01futabato10.hateblo.jp/entry/2022/12/02/095031" target="_blank" rel="noopener"
 &gt;https://01futabato10.hateblo.jp/entry/2022/12/02/095031&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そのうえで、以下のバッチファイルを作成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wsl --shutdown
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;diskpart /s sample.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとはこのバッチファイルを実行するだけで OK です。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://01futabato10.hateblo.jp/entry/2022/12/02/095031" target="_blank" rel="noopener"
 &gt;https://01futabato10.hateblo.jp/entry/2022/12/02/095031&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/siruku6/items/c91a40d460095013540d" target="_blank" rel="noopener"
 &gt;https://qiita.com/siruku6/items/c91a40d460095013540d&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://dev.classmethod.jp/articles/windows-virtual-disk-compression/" target="_blank" rel="noopener"
 &gt;https://dev.classmethod.jp/articles/windows-virtual-disk-compression/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[python] ONVIF 対応カメラの RTSP 接続文字列を取得する</title><link>https://blog.ponkotools.com/posts/2024/02/15/rtsp/</link><pubDate>Thu, 15 Feb 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/02/15/rtsp/</guid><description>&lt;p&gt;ネットワークカメラの映像を取得するためにまず RTSP の接続文字列を取得する必要があったので、ONVIF の Profile S から取得してみました。&lt;/p&gt;
&lt;p&gt;ONVIF Profile S の仕様は以下にあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.onvif.org/profiles/specifications/" target="_blank" rel="noopener"
 &gt;https://www.onvif.org/profiles/specifications/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;尚、単純に RTSP の接続文字列を取得したいだけなら ONVIF Device Manager というツールがあるので、それを使ったほうが楽です。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;python 3.11&lt;/li&gt;
&lt;li&gt;onvif-zeep 0.2.12&lt;/li&gt;
&lt;li&gt;onvif2-zeep 0.3.4&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ONVIF クライアントの python 実装である &lt;code&gt;onvif-zeep&lt;/code&gt; &lt;code&gt;onvif2-zeep&lt;/code&gt; を使ってみました。&lt;br&gt;
この２つの違いですが、以下のページによれば、&lt;code&gt;onvif2-zeep&lt;/code&gt; のほうは WSDL と H.265 に対応しているようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://pypi.org/project/onvif2-zeep/" target="_blank" rel="noopener"
 &gt;https://pypi.org/project/onvif2-zeep/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下、&lt;code&gt;onvif-zeep&lt;/code&gt; &lt;code&gt;onvif2-zeep&lt;/code&gt; それぞれのサンプルコードです。&lt;/p&gt;
&lt;h2 id="onvif-zeep-でのサンプル"&gt;&lt;a href="#onvif-zeep-%e3%81%a7%e3%81%ae%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;onvif-zeep でのサンプル
&lt;/h2&gt;&lt;h3 id="準備"&gt;&lt;a href="#%e6%ba%96%e5%82%99" class="header-anchor"&gt;&lt;/a&gt;準備
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install onvif-zeep
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;onvif&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ONVIFCamera&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_all_rtsp_urls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;camera_ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ONVIFデバイスに接続&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ONVIFCamera&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;camera_ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# プロファイルを取得&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;media&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;camera&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_media_service&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;profiles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;media&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetProfiles&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#print(profiles)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# すべてのプロファイルに対して RTSP URL を取得&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;profiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;token&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stream_uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;media&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetStreamUri&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;StreamSetup&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Stream&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;RTP-Unicast&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Transport&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Protocol&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;RTSP&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;ProfileToken&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stream_uri&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Uri&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;camera_ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;192.168.0.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;username&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;password&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;get_all_rtsp_urls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;camera_ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="onvif2-zeep-のサンプル"&gt;&lt;a href="#onvif2-zeep-%e3%81%ae%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;onvif2-zeep のサンプル
&lt;/h2&gt;&lt;h3 id="準備-1"&gt;&lt;a href="#%e6%ba%96%e5%82%99-1" class="header-anchor"&gt;&lt;/a&gt;準備
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install onvif2-zeep
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="wsdl-のダウンロード"&gt;&lt;a href="#wsdl-%e3%81%ae%e3%83%80%e3%82%a6%e3%83%b3%e3%83%ad%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;WSDL のダウンロード
&lt;/h4&gt;&lt;p&gt;&lt;code&gt;onvif2-zeep&lt;/code&gt; を使用する場合、WSDL のファイル一式が必要なようです。&lt;br&gt;
以下のリポジトリからダウンロードできます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/onvif/specs" target="_blank" rel="noopener"
 &gt;https://github.com/onvif/specs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="サンプルコード-1"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89-1" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h3&gt;&lt;p&gt;上記のコードから以下の２箇所を変更するだけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from onvif2 import ONVIFCamera
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;camera = ONVIFCamera(camera_ip, 80, username, password, &amp;#39;./wsdl&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;ONVIFCamera&lt;/code&gt; の引数の最後で、WSDL ファイルのあるパスを指定します。&lt;/p&gt;
&lt;h2 id="実行結果"&gt;&lt;a href="#%e5%ae%9f%e8%a1%8c%e7%b5%90%e6%9e%9c" class="header-anchor"&gt;&lt;/a&gt;実行結果
&lt;/h2&gt;&lt;p&gt;Panasonic のカメラで試した結果が以下となります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;H264_1280x960: rtsp://192.168.0.1/ONVIF/MediaInput?profile=1_def_profile8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;H264_800x600: rtsp://192.168.0.1/ONVIF/MediaInput?profile=1_def_profile7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;H264_640x480: rtsp://192.168.0.1/ONVIF/MediaInput?profile=1_def_profile6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;H264_320x240: rtsp://192.168.0.1/ONVIF/MediaInput?profile=1_def_profile5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;JPEG_1280x960: rtsp://192.168.0.1/ONVIF/MediaInput?profile=1_def_profile4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;JPEG_800x600: rtsp://192.168.0.1/ONVIF/MediaInput?profile=1_def_profile3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;JPEG_640x480: rtsp://192.168.0.1/ONVIF/MediaInput?profile=1_def_profile2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;JPEG_320x240: rtsp://192.168.0.1/ONVIF/MediaInput?profile=1_def_profile1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ただ、H.265 のストリームがあるカメラ場合、&lt;code&gt;onvif-zeep&lt;/code&gt; &lt;code&gt;onvif2-zeep&lt;/code&gt; のどちらで試しても以下のように &lt;code&gt;Unknown error: Configuration not complete&lt;/code&gt; のエラーが出て取得することができませんでした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;H26x_1: Unknown error: Configuration not complete
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;H26x_2: Unknown error: Configuration not complete
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;JPEG_1: rtsp://192.168.0.1/ONVIF/MediaInput?profile=def_profile5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;JPEG_2: rtsp://192.168.0.1/ONVIF/MediaInput?profile=def_profile6
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;カメラ側のプロファイル設定の問題のような気がしますが、よくわかりませんでした。&lt;/p&gt;
&lt;p&gt;ちなみに、他に TOA のカメラも試しましたが、こちらは H.265 の場合でも問題なく取得することができました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.onvif.org/profiles/specifications/" target="_blank" rel="noopener"
 &gt;https://www.onvif.org/profiles/specifications/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Gymnasium の環境を動かしてみる</title><link>https://blog.ponkotools.com/posts/2024/02/12/gymnasium/</link><pubDate>Mon, 12 Feb 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/02/12/gymnasium/</guid><description>&lt;p&gt;強化学習について勉強しようと思い、まずはサンプルとしてよく取り上げられる OpenAI の gym の CartPole などを動かそうとしてみたところ、上手く動きませんでした。&lt;br&gt;
調べてみたところ、gym は現在ではもう更新されておらず、代わりに gym を fork した gymnasium というのがあるようなので、こちらを使って動かしてみました。&lt;/p&gt;
&lt;p&gt;実行環境は docker を使って構築します。&lt;br&gt;
とりあえず学習・推論はせず、単純に動かすだけです。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;WSL2(Ubuntu 22.04)&lt;/li&gt;
&lt;li&gt;docker 24.0.7&lt;/li&gt;
&lt;li&gt;python 3.11&lt;/li&gt;
&lt;li&gt;swig 4.2.0&lt;/li&gt;
&lt;li&gt;gymnasium 0.29.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dockerfile"&gt;&lt;a href="#dockerfile" class="header-anchor"&gt;&lt;/a&gt;Dockerfile
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;FROM python:3.11
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 先に swig をインストールしておかないと gymnasium のインストールに失敗しました
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RUN pip install swig
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RUN pip install gymnasium[box2d]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CMD [ &amp;#34;/bin/bash&amp;#34; ]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="コンテナの起動"&gt;&lt;a href="#%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e3%81%ae%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;コンテナの起動
&lt;/h3&gt;&lt;p&gt;GUI を動かすので、コンテナは以下のように起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -it --rm &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v &lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;/workspace:/workspace &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /etc/group:/etc/group:ro &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /etc/passwd:/etc/passwd:ro &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -u &lt;span class="k"&gt;$(&lt;/span&gt;id -u &lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;:&lt;span class="k"&gt;$(&lt;/span&gt;id -g &lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e DISPLAY &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /tmp/.X11-unix:/tmp/.X11-unix:rw &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --workdir /workspace &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; imagename
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これについては以下が参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/Spritaro/items/f907a9b52cb78e4fbec0" target="_blank" rel="noopener"
 &gt;https://qiita.com/Spritaro/items/f907a9b52cb78e4fbec0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="cartpole-のサンプル"&gt;&lt;a href="#cartpole-%e3%81%ae%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;CartPole のサンプル
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gymnasium&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;gym&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 環境を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# render_mode は描画モードの指定。human は人間が見てわかるように動画として表示するという意味&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gym&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;CartPole-v1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;render_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;human&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;episode&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 環境をリセット&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;observation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 行動をランダムに選択&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action_space&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# これがエージェントの行動になるので、本来はAIが行動を決定するべきところ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 選択した行動を実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;observation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reward&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;terminated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;truncated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#print(env.render()) # 状態の可視化(human の場合は不要)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 終了した場合、次のエピソードへ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;terminated&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;truncated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Episode&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;episode&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; finished after &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; timesteps&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="337px" data-flex-grow="140" height="434" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2024/02/12/gymnasium/cartpole.webp" width="610"&gt;&lt;/p&gt;
&lt;h2 id="lunarlander-のサンプル"&gt;&lt;a href="#lunarlander-%e3%81%ae%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;LunarLander のサンプル
&lt;/h2&gt;&lt;p&gt;同様に以下のようにして LunarLander も動きました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gymnasium&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;gym&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 環境を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# render_mode は描画モードの指定。human は人間が見てわかるように動画として表示するという意味&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gym&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;LunarLander-v2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;render_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;human&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;episode&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 環境をリセット&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;observation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 行動をランダムに選択&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action_space&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# これがエージェントの行動になるので、本来はAIが行動を決定するべきところ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 選択した行動を実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;observation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reward&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;terminated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;truncated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#print(env.render()) # 状態の可視化(human の場合は不要)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 終了した場合、次のエピソードへ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;terminated&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;truncated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Episode&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;episode&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; finished after &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; timesteps&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="339px" data-flex-grow="141" height="431" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2024/02/12/gymnasium/lunaerlander.webp" width="609"&gt;&lt;/p&gt;
&lt;h2 id="frozenlake-のサンプル"&gt;&lt;a href="#frozenlake-%e3%81%ae%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;FrozenLake のサンプル
&lt;/h2&gt;&lt;p&gt;同様に以下のようにして FrozenLake も動きました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gymnasium&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;gym&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 環境を作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# render_mode は描画モードの指定。human は人間が見てわかるように動画として表示するという意味&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gym&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;FrozenLake-v1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;render_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;human&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;episode&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 環境をリセット、現在の観測値（observation）と情報（info）を取得&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;observation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 行動をランダムに選択&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action_space&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# これがエージェントの行動になるので、本来はAIが行動を決定するべきところ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 選択した行動を実行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;observation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reward&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;terminated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;truncated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#print(env.render()) # 状態の可視化(human の場合は不要)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 終了した場合、次のエピソードへ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;terminated&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;truncated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Episode&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;episode&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; finished after &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; timesteps&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="221px" data-flex-grow="92" height="287" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2024/02/12/gymnasium/fronzelake.png" width="265"&gt;&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/openai/gym/issues/3240" target="_blank" rel="noopener"
 &gt;https://github.com/openai/gym/issues/3240&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://note.com/kikaben/n/n57584c49d5c2" target="_blank" rel="noopener"
 &gt;https://note.com/kikaben/n/n57584c49d5c2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/Spritaro/items/f907a9b52cb78e4fbec0" target="_blank" rel="noopener"
 &gt;https://qiita.com/Spritaro/items/f907a9b52cb78e4fbec0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://amateur-engineer-blog.com/reinforce-learning-getting-started/#toc5" target="_blank" rel="noopener"
 &gt;https://amateur-engineer-blog.com/reinforce-learning-getting-started/#toc5&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Windows と Ubuntu でマウスとキーボードを共有する</title><link>https://blog.ponkotools.com/posts/2024/01/26/barrier/</link><pubDate>Fri, 26 Jan 2024 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2024/01/26/barrier/</guid><description>&lt;p&gt;Barrier というソフトを使って、マウスとキーボードを共有します。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Windows 10
&lt;ul&gt;
&lt;li&gt;barrier 2.4.0&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ubuntu 20.04
&lt;ul&gt;
&lt;li&gt;barrier 2.3.2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Barrier を使う場合、どちらかをサーバーとして設定する必要がありますが、今回は Windows をサーバーとしました。&lt;/p&gt;
&lt;h2 id="windows-側"&gt;&lt;a href="#windows-%e5%81%b4" class="header-anchor"&gt;&lt;/a&gt;Windows 側
&lt;/h2&gt;&lt;h3 id="インストール"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;インストール
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/debauchee/barrier/releases" target="_blank" rel="noopener"
 &gt;GitHub の Releases&lt;/a&gt; から最新の exe をダウンロードしてインストールします。&lt;br&gt;
Bonjourというソフトをインストールするかどうか聞かれますが、インストールしませんでした。&lt;/p&gt;
&lt;h3 id="設定"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;設定
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;「サーバー」にチェックを入れる&lt;/li&gt;
&lt;li&gt;「サーバーの構成設定」を選択し、「モニタの結びつき」で任意のマスをクリックして、クライアント側のモニターを追加する
&lt;ul&gt;
&lt;li&gt;モニター名を後述のクライアント側の名前に合わせて入力する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;メニューバーから、「Barrier &amp;gt; 設定の変更」を選択し、「SSL を使用」のチェックを外す。&lt;/li&gt;
&lt;li&gt;開始を押す&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ubuntu-側"&gt;&lt;a href="#ubuntu-%e5%81%b4" class="header-anchor"&gt;&lt;/a&gt;Ubuntu 側
&lt;/h2&gt;&lt;h3 id="インストール-1"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab-1" class="header-anchor"&gt;&lt;/a&gt;インストール
&lt;/h3&gt;&lt;p&gt;以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install barrier
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="設定-1"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a-1" class="header-anchor"&gt;&lt;/a&gt;設定
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;「クライアント」にチェックを入れる&lt;/li&gt;
&lt;li&gt;「サーバーIP」にIPアドレスを入力する&lt;/li&gt;
&lt;li&gt;メニューバーから、「Barrier &amp;gt; Change Settings」を選択し、「Enable SSL」のチェックを外す。&lt;/li&gt;
&lt;li&gt;開始を押す&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="追加の設定"&gt;&lt;a href="#%e8%bf%bd%e5%8a%a0%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;追加の設定
&lt;/h2&gt;&lt;p&gt;ログイン画面（ロック画面）になるとマウスとキーボードが効かなくなるので、以下の設定も行いました。&lt;/p&gt;
&lt;h3 id="windows-サーバー-側"&gt;&lt;a href="#windows-%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc-%e5%81%b4" class="header-anchor"&gt;&lt;/a&gt;Windows (サーバー) 側
&lt;/h3&gt;&lt;p&gt;Barrier の設定で、権限昇格を「常に」に変更しました。&lt;br&gt;
恐らくセキュリティ的によろしくないので、やるなら自己責任でお願いします。&lt;/p&gt;
&lt;h3 id="ubuntu-クライアント-側"&gt;&lt;a href="#ubuntu-%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88-%e5%81%b4" class="header-anchor"&gt;&lt;/a&gt;Ubuntu (クライアント) 側
&lt;/h3&gt;&lt;p&gt;Ubuntu 20.04 を使用している場合、GNOME デスクトップ環境がデフォルトで採用されているため、GDM (GNOME Display Manager) の設定を変更しました。&lt;/p&gt;
&lt;p&gt;まず、GDMの設定ファイルを開きます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo nano /etc/gdm3/custom.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;[daemon] セクションに以下を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;daemon&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Greeter-setup-script&lt;span class="o"&gt;=&lt;/span&gt;/usr/bin/numlockx on
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;変更を有効にするためにGDMを再起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo service gdm restart
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ただし、セキュリティ的にはよろしくないので、やるなら自己責任でお願いします。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://nanjib.com/archives/1587" target="_blank" rel="noopener"
 &gt;https://nanjib.com/archives/1587&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://ossyaritoori.hatenablog.com/entry/2019/09/26/Barrier%E3%82%92%E7%94%A8%E3%81%84%E3%81%A6%E8%A4%87%E6%95%B0%E3%81%AEPC%E9%96%93%E3%81%A7%E3%83%9E%E3%82%A6%E3%82%B9%E3%83%BB%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E5%85%B1%E6%9C%89" target="_blank" rel="noopener"
 &gt;https://ossyaritoori.hatenablog.com/entry/2019/09/26/Barrier%E3%82%92%E7%94%A8%E3%81%84%E3%81%A6%E8%A4%87%E6%95%B0%E3%81%AEPC%E9%96%93%E3%81%A7%E3%83%9E%E3%82%A6%E3%82%B9%E3%83%BB%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E5%85%B1%E6%9C%89&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>GitLab Pages でディレクトリ一覧を表示したい</title><link>https://blog.ponkotools.com/posts/2023/12/25/gitlab-pages/</link><pubDate>Mon, 25 Dec 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/12/25/gitlab-pages/</guid><description>&lt;p&gt;GitLab Pages で公開しているサイトにアクセスしたときに、配下ディレクトリの一覧を表示させる方法です。&lt;/p&gt;
&lt;p&gt;GitLab 12.8 までは nginx の autoindex を有効にして index of で表示させることができたようですが、セキュリティの観点からその機能は削除されたそうです。&lt;/p&gt;
&lt;p&gt;なので、どうにかしてインデックスページを作成し、GitLab Pages に公開するしかありません。
例えば、Hugo や Jekyll で Sitemap やインデックスページの自動生成機能を使う方法があるようです。&lt;/p&gt;
&lt;p&gt;ただ、今回私はシェルスクリプトファイルで作成することにしました。&lt;/p&gt;
&lt;p&gt;以下、サンプルです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 公開ディレクトリ内のディレクトリ一覧を取得&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;dirs&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;public/*/&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# HTMLで一覧を表示するための変数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;list&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;lt;ul&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ディレクトリのHTMLリストを生成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; d in &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# フォルダ一覧のみに制限するため、publicディレクトリ内のサブディレクトリのみを対象としています。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$d&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed -e &lt;span class="s1"&gt;&amp;#39;s/public\///&amp;#39;&lt;/span&gt; -e &lt;span class="s1"&gt;&amp;#39;s/\///&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;list&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$list&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;#39;&lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;list&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$list&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/ul&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# index.htmlファイルを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;タイトル&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; public/index.html &lt;span class="s"&gt;&amp;lt;&amp;lt; EOF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;&amp;lt;html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;lt;head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;lt;meta charset=&amp;#34;UTF-8&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;lt;title&amp;gt;$title&amp;lt;/title&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;lt;/head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;lt;h1&amp;gt;$title&amp;lt;/h1&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; $list
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;lt;/body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;&amp;lt;/html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これを、&lt;code&gt;.gitlab-ci.yml&lt;/code&gt; の script の最後に実行すれば OK です。&lt;/p&gt;
&lt;p&gt;上記はディレクトリに限定していますが、応用でファイル一覧を出力できると思います。&lt;/p&gt;</description></item><item><title>GitLab Pages でブランチ毎にディレクトリを分けて公開したい</title><link>https://blog.ponkotools.com/posts/2023/12/20/gitlab-pages/</link><pubDate>Wed, 20 Dec 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/12/20/gitlab-pages/</guid><description>&lt;p&gt;mkdocs で作成したサイトを GitLab Pages で公開していたのですが、これをブランチ毎にディレクトリを分けて公開するようにしました。&lt;/p&gt;
&lt;p&gt;基本的には、キャッシュを有効にするだけで可能です。&lt;br&gt;
各ブランチでの成果物も一緒に Pages で公開したいため、キャッシュのキーは固定値にします。&lt;br&gt;
以下、 &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; の抜粋です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;build&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mkdocs build&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;rm -rf public/${CI_COMMIT_REF_NAME}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mv site public/${CI_COMMIT_REF_NAME}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;artifacts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;public&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ブランチ毎に別のキャッシュを利用したい場合はブランチ名をキーにするが、&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 今回は全ブランチのビルド結果も一緒に公開したいため、キーは全ブランチで共通の固定値にする&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;common-key&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;#key: &amp;#34;$CI_COMMIT_REF_NAME&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;public&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;site&lt;/code&gt; ディレクトリが mkdocs の成果物が入っているディレクトリですが、これを &lt;code&gt;public/ブランチ名&lt;/code&gt; に配置しています。&lt;/p&gt;
&lt;h2 id="注意点"&gt;&lt;a href="#%e6%b3%a8%e6%84%8f%e7%82%b9" class="header-anchor"&gt;&lt;/a&gt;注意点
&lt;/h2&gt;&lt;p&gt;デフォルトでは、保護されたブランチと保護されていないブランチではキャッシュが共有されないため、この場合はプロジェクトの設定変更が必要です。&lt;br&gt;
これを知らずに何度試してもキャッシュが共有されずはまっていました・・・。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gitlab-docs.creationline.com/ee/ci/caching/#use-the-same-cache-for-all-branches" target="_blank" rel="noopener"
 &gt;https://gitlab-docs.creationline.com/ee/ci/caching/#use-the-same-cache-for-all-branches&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;変更する設定は以下です。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;サイドメニューより、&lt;code&gt;Settings&lt;/code&gt; &amp;gt; &lt;code&gt;CI/CD&lt;/code&gt; を選択&lt;/li&gt;
&lt;li&gt;&lt;code&gt;General pipelines&lt;/code&gt; を開く&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Use separate caches for protected branches&lt;/code&gt; のチェックボックスをオフにする&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Save changes&lt;/code&gt; をクリックして保存&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://dev.to/zenika/gitlab-pages-preview-the-no-compromise-hack-to-serve-per-branch-pages-5599" target="_blank" rel="noopener"
 &gt;https://dev.to/zenika/gitlab-pages-preview-the-no-compromise-hack-to-serve-per-branch-pages-5599&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://gist.github.com/donaldpipowitch/2590b20520b2cf6ae01aab4f7b55f8fa" target="_blank" rel="noopener"
 &gt;https://gist.github.com/donaldpipowitch/2590b20520b2cf6ae01aab4f7b55f8fa&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://gitlab-docs.creationline.com/ee/ci/caching/#use-the-same-cache-for-all-branches" target="_blank" rel="noopener"
 &gt;https://gitlab-docs.creationline.com/ee/ci/caching/#use-the-same-cache-for-all-branches&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] ModuleNotFoundError: No module named 'websockets.legacy' のエラーが出た</title><link>https://blog.ponkotools.com/posts/2023/12/01/python/</link><pubDate>Fri, 01 Dec 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/12/01/python/</guid><description>&lt;p&gt;Python のアプリを Nuitka で実行ファイルにして動かすと、Websockets に関するエラーが出ました。&lt;/p&gt;
&lt;p&gt;尚、python で実行したときには正常に動作しています。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Python 3.11&lt;/li&gt;
&lt;li&gt;Nuitka 1.9.2&lt;/li&gt;
&lt;li&gt;Websockets 11.0.3&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="エラーの内容"&gt;&lt;a href="#%e3%82%a8%e3%83%a9%e3%83%bc%e3%81%ae%e5%86%85%e5%ae%b9" class="header-anchor"&gt;&lt;/a&gt;エラーの内容
&lt;/h2&gt;&lt;p&gt;具体的には以下のようなエラーが出ました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Traceback (most recent call last):
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/foo/main.py&amp;#34;, line 36, in subprocess
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/foo/asyncio/runners.py&amp;#34;, line 190, in run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/foo/asyncio/runners.py&amp;#34;, line 118, in run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/foo/asyncio/base_events.py&amp;#34;, line 653, in run_until_complete
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/foo/websocket_manager.py&amp;#34;, line 47, in run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/foo/websocket_client.py&amp;#34;, line 38, in run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/foo/websockets/imports.py&amp;#34;, line 77, in __getattr__
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; File &amp;#34;/foo/websockets/imports.py&amp;#34;, line 27, in import_name
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ModuleNotFoundError: No module named &amp;#39;websockets.legacy&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="とりあえずの対処法"&gt;&lt;a href="#%e3%81%a8%e3%82%8a%e3%81%82%e3%81%88%e3%81%9a%e3%81%ae%e5%af%be%e5%87%a6%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;とりあえずの対処法
&lt;/h2&gt;&lt;p&gt;以下に同じエラーの報告がありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/python-websockets/websockets/issues/974" target="_blank" rel="noopener"
 &gt;https://github.com/python-websockets/websockets/issues/974&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上記を参考に以下のように変更すればとりあえず解決しました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;変更前&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;import websockets
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;async for websocket in websockets.connect(uri):
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;変更後&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;import websockets.client
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;async for websocket in websockets.client.connect(uri):
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="本来の解決方法"&gt;&lt;a href="#%e6%9c%ac%e6%9d%a5%e3%81%ae%e8%a7%a3%e6%b1%ba%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;本来の解決方法
&lt;/h2&gt;&lt;p&gt;上記のコードですが、どうやらこれは古い記述方法みたいです。&lt;br&gt;
最近の websockets (11.x 以降) では、接続の作成と処理は以下のように行うことを推奨しているようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;import websockets
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;while True:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; try:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; async with websockets.connect(uri) as websocket:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # メッセージ処理 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; except Exception:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # ここに再接続ロジックなど 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; await asyncio.sleep(retry_delay)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ただし、これで今回のエラーが解決するかどうかは試していません。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/python-websockets/websockets/issues/974" target="_blank" rel="noopener"
 &gt;https://github.com/python-websockets/websockets/issues/974&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] Windows コンテナを動かす</title><link>https://blog.ponkotools.com/posts/2023/11/21/docker-windows/</link><pubDate>Tue, 21 Nov 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/11/21/docker-windows/</guid><description>&lt;p&gt;Docker Desktop を使わずに、Windows 10 に Docker のバイナリを直接インストールして、Windows コンテナを動かすまでをやってみました。&lt;/p&gt;
&lt;p&gt;やり方は以下のドキュメントに記載されていました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/engine/install/binaries/#install-server-and-client-binaries-on-windows" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/engine/install/binaries/#install-server-and-client-binaries-on-windows&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;記載の通り、これで動かせるようになるのは Windows コンテナのみで、Linux コンテナは動かせません。&lt;br&gt;
Windows 上で Linux コンテナを動かしたい場合は、WSL を使う方法などがあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/01/wsl2-ubuntu-docker.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/01/wsl2-ubuntu-docker.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Windows 10 Pro&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="windows-の機能の有効化"&gt;&lt;a href="#windows-%e3%81%ae%e6%a9%9f%e8%83%bd%e3%81%ae%e6%9c%89%e5%8a%b9%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;Windows の機能の有効化
&lt;/h2&gt;&lt;p&gt;コントロールパネルの [Windows の機能の有効化または無効化] より、&lt;code&gt;コンテナ&lt;/code&gt; にチェックを入れます。&lt;br&gt;
これにチェックが入っていないと Docker コンテナが動きませんでした。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="270px" data-flex-grow="112" height="368" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2023/11/21/docker-windows/container.png" width="415"&gt;&lt;/p&gt;
&lt;p&gt;また、Hyper-V の有効化が必要という記事も見かけましたが、私の環境では Hyper-V を有効化しなくても動きました。&lt;br&gt;
Hyper-V については以下を参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/ja-jp/virtualization/hyper-v-on-windows/reference/hyper-v-requirements" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/ja-jp/virtualization/hyper-v-on-windows/reference/hyper-v-requirements&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="インストール方法"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;インストール方法
&lt;/h2&gt;&lt;h3 id="バイナリのダウンロード"&gt;&lt;a href="#%e3%83%90%e3%82%a4%e3%83%8a%e3%83%aa%e3%81%ae%e3%83%80%e3%82%a6%e3%83%b3%e3%83%ad%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;バイナリのダウンロード
&lt;/h3&gt;&lt;p&gt;以下からインストールしたい Docker のバージョンのバイナリファイルをダウンロードします。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://download.docker.com/win/static/stable/x86_64/" target="_blank" rel="noopener"
 &gt;https://download.docker.com/win/static/stable/x86_64/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;現時点で最新の 24.0.7 をダウンロードしました。&lt;/p&gt;
&lt;h3 id="programfiles-への展開"&gt;&lt;a href="#programfiles-%e3%81%b8%e3%81%ae%e5%b1%95%e9%96%8b" class="header-anchor"&gt;&lt;/a&gt;ProgramFiles への展開
&lt;/h3&gt;&lt;p&gt;ダウンロードした zip を ProgramFiles に展開するため、PowerShell を管理者で起動して以下を実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; Expand-Archive &amp;lt;ダウンロードした zip へのパス&amp;gt; -DestinationPath &lt;span class="nv"&gt;$Env&lt;/span&gt;:ProgramFiles
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;$Env:ProgramFiles&lt;/code&gt; は環境変数 &lt;code&gt;ProgramFiles&lt;/code&gt; を表示しており、通常は &lt;code&gt;C:\Program Files&lt;/code&gt; というパスになります。&lt;br&gt;
以降のコマンドは全て PowerShell で実行します。&lt;/p&gt;
&lt;h3 id="サービスへの登録"&gt;&lt;a href="#%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%81%b8%e3%81%ae%e7%99%bb%e9%8c%b2" class="header-anchor"&gt;&lt;/a&gt;サービスへの登録
&lt;/h3&gt;&lt;p&gt;Docker をサービスへ登録します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$Env&lt;/span&gt;:ProgramFiles&lt;span class="se"&gt;\D&lt;/span&gt;ocker&lt;span class="se"&gt;\d&lt;/span&gt;ockerd --register-service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;&amp;amp;&lt;/code&gt; は、PowerShell においてコマンドやスクリプトを呼び出す演算子です。&lt;br&gt;
従って、環境変数展開後の &lt;code&gt;C:\ProgramFiles\Docker\dockerd&lt;/code&gt; という文字列をコマンドとして実行しています。&lt;/p&gt;
&lt;h3 id="サービスの開始"&gt;&lt;a href="#%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%81%ae%e9%96%8b%e5%a7%8b" class="header-anchor"&gt;&lt;/a&gt;サービスの開始
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; Start-Service docker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="動作確認"&gt;&lt;a href="#%e5%8b%95%e4%bd%9c%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;動作確認
&lt;/h3&gt;&lt;p&gt;Hello World イメージを動かしてみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$Env&lt;/span&gt;:ProgramFiles&lt;span class="se"&gt;\D&lt;/span&gt;ocker&lt;span class="se"&gt;\d&lt;/span&gt;ocker run hello-world:nanoserver
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;基本的にはこれで上手くいくはずですが、プロキシ環境下の場合は、後述するプロキシ設定が必要になります。&lt;/p&gt;
&lt;h2 id="環境変数へパスを通す"&gt;&lt;a href="#%e7%92%b0%e5%a2%83%e5%a4%89%e6%95%b0%e3%81%b8%e3%83%91%e3%82%b9%e3%82%92%e9%80%9a%e3%81%99" class="header-anchor"&gt;&lt;/a&gt;環境変数へパスを通す
&lt;/h2&gt;&lt;p&gt;毎回 &lt;code&gt;&amp;amp;$Env:ProgramFiles\Docker\docker&lt;/code&gt; と打つのは面倒なため、&lt;code&gt;$env:ProgramFiles\docker\&lt;/code&gt; をPATHに追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; &lt;span class="o"&gt;[&lt;/span&gt;Environment&lt;span class="o"&gt;]&lt;/span&gt;::SetEnvironmentVariable&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Path&amp;#34;&lt;/span&gt;, &lt;span class="nv"&gt;$env&lt;/span&gt;:Path + &lt;span class="s2"&gt;&amp;#34;;&lt;/span&gt;&lt;span class="nv"&gt;$env&lt;/span&gt;&lt;span class="s2"&gt;:ProgramFiles\docker\&amp;#34;, [EnvironmentVariableTarget]::Machine)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;PowerShell を一度閉じて、再度開きます。&lt;br&gt;
これで以下のように &lt;code&gt;docker&lt;/code&gt; と打つだけで実行できるようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; docker run hello-world:nanoserver
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="プロキシ設定"&gt;&lt;a href="#%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;プロキシ設定
&lt;/h2&gt;&lt;p&gt;プロキシ環境下では、プロキシサーバーの設定を行っていないと Docker イメージを pull できません。&lt;br&gt;
設定方法については以下に記載がありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/ja-jp/virtualization/windowscontainers/manage-docker/configure-docker-daemon" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/ja-jp/virtualization/windowscontainers/manage-docker/configure-docker-daemon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;環境変数 &lt;code&gt;HTTP_PROXY&lt;/code&gt; &lt;code&gt;HTTPS_PROXY&lt;/code&gt; を設定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; &lt;span class="o"&gt;[&lt;/span&gt;Environment&lt;span class="o"&gt;]&lt;/span&gt;::SetEnvironmentVariable&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;HTTP_PROXY&amp;#34;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;http://&amp;lt;IP address&amp;gt;:&amp;lt;port&amp;gt;&amp;#34;&lt;/span&gt;, &lt;span class="o"&gt;[&lt;/span&gt;EnvironmentVariableTarget&lt;span class="o"&gt;]&lt;/span&gt;::Machine&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;設定後、Docker サービスを再起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; Restart-Service docker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="docker-クライアントのプロキシ設定"&gt;&lt;a href="#docker-%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e3%81%ae%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;docker クライアントのプロキシ設定
&lt;/h3&gt;&lt;p&gt;Linux では &lt;code&gt;~/.docker/config.json&lt;/code&gt; に設定しますが、Windows では &lt;code&gt;%USERPROFILE%\.docker\config.json&lt;/code&gt; に設定します。&lt;/p&gt;
&lt;p&gt;以下のように設定しておくことで、Dockerfile のビルドを行う際に &lt;code&gt;--build-args&lt;/code&gt; などで都度プロキシの設定を行う必要がなくなります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;proxies&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;default&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;httpProxy&amp;#34;: &amp;#34;http://&amp;lt;IPアドレス&amp;gt;:&amp;lt;port&amp;gt;&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;httpsProxy&amp;#34;: &amp;#34;http://&amp;lt;IPアドレス&amp;gt;:&amp;lt;port&amp;gt;&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;noProxy&amp;#34;: &amp;#34;localhost,127.0.0.1,host.docker.internal&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;もしかしたら、一度 Docker サービスを再起動する必要があるかもしれません。&lt;/p&gt;
&lt;h2 id="エラーが発生した場合"&gt;&lt;a href="#%e3%82%a8%e3%83%a9%e3%83%bc%e3%81%8c%e7%99%ba%e7%94%9f%e3%81%97%e3%81%9f%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;エラーが発生した場合
&lt;/h2&gt;&lt;p&gt;次のようなエラーが発生した場合、Docker サービスが起動していないか、プロキシにより通信が通っていないかのどちらか可能性が高いです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Unable to find image &lt;span class="s1"&gt;&amp;#39;hello-world:nanoserver&amp;#39;&lt;/span&gt; locally
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker: Error response from daemon: Get &lt;span class="s2"&gt;&amp;#34;https://registry-1.docker.io/v2/&amp;#34;&lt;/span&gt;: net/http: request canceled &lt;span class="k"&gt;while&lt;/span&gt; waiting &lt;span class="k"&gt;for&lt;/span&gt; connection &lt;span class="o"&gt;(&lt;/span&gt;Client.Timeout exceeded &lt;span class="k"&gt;while&lt;/span&gt; awaiting headers&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;See &lt;span class="s1"&gt;&amp;#39;docker run --help&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、次のようなエラーが発生した場合、[Windows の機能の有効化または無効化] で &lt;code&gt;コンテナ&lt;/code&gt; にチェックが入っていない可能性があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker: Error response from daemon: hcs::CreateComputeSystem d5ccfe373c27d9053c87689f60075aed9acdca360d6cd42e1abdc5591bb60cbc: The request is not supported.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="アンインストール"&gt;&lt;a href="#%e3%82%a2%e3%83%b3%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;アンインストール
&lt;/h2&gt;&lt;p&gt;サービスから Docker を削除します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$Env&lt;/span&gt;:ProgramFiles&lt;span class="se"&gt;\D&lt;/span&gt;ocker&lt;span class="se"&gt;\d&lt;/span&gt;ockerd --unregister-service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これだけではまだ完全にサービスは削除されていないので、一度 OS を再起動します。&lt;br&gt;
その後、docker のフォルダを削除します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; Remove-item -Recurse &lt;span class="nv"&gt;$Env&lt;/span&gt;:ProgramFiles&lt;span class="se"&gt;\D&lt;/span&gt;ocker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="アップデート"&gt;&lt;a href="#%e3%82%a2%e3%83%83%e3%83%97%e3%83%87%e3%83%bc%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;アップデート
&lt;/h2&gt;&lt;p&gt;現在のバージョンをアンインストールし、新しいバージョンをインストールします。&lt;/p&gt;
&lt;h2 id="余談他の-windows-コンテナを動かしてみた"&gt;&lt;a href="#%e4%bd%99%e8%ab%87%e4%bb%96%e3%81%ae-windows-%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e3%82%92%e5%8b%95%e3%81%8b%e3%81%97%e3%81%a6%e3%81%bf%e3%81%9f" class="header-anchor"&gt;&lt;/a&gt;余談：他の Windows コンテナを動かしてみた
&lt;/h2&gt;&lt;p&gt;python3.11 の Windows コンテナを動かしてみました。&lt;/p&gt;
&lt;p&gt;python イメージのタグ一覧が以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/_/python" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/_/python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Windows コンテナをベースとしている python3.11 のイメージとして以下の２つがあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3.11-windowsservercore-ltsc2022&lt;/li&gt;
&lt;li&gt;3.11-windowsservercore-1809&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;私の PC では、&lt;code&gt;3.11-windowsservercore-ltsc2022&lt;/code&gt; は動かず、&lt;code&gt;3.11-windowsservercore-1809&lt;/code&gt; は動きました。&lt;br&gt;
ベースとしている Windows コンテナの詳細は以下で確認できます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/_/microsoft-windows-servercore" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/_/microsoft-windows-servercore&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.ulvaniac.co.jp/2023/09/06/docker-desktop%E3%82%92%E4%BD%BF%E3%82%8F%E3%81%AA%E3%81%84windows%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E5%8B%95%E4%BD%9C%E6%96%B9%E6%B3%95/" target="_blank" rel="noopener"
 &gt;https://www.ulvaniac.co.jp/2023/09/06/docker-desktop%E3%82%92%E4%BD%BF%E3%82%8F%E3%81%AA%E3%81%84windows%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E5%8B%95%E4%BD%9C%E6%96%B9%E6%B3%95/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://and-engineer.com/articles/YcGZxhYAACUAbPjg" target="_blank" rel="noopener"
 &gt;https://and-engineer.com/articles/YcGZxhYAACUAbPjg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/SGTY/items/1126e0b95c35843fd8c5" target="_blank" rel="noopener"
 &gt;https://qiita.com/SGTY/items/1126e0b95c35843fd8c5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.shibata.tech/entry/2016/08/05/233212" target="_blank" rel="noopener"
 &gt;https://blog.shibata.tech/entry/2016/08/05/233212&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/ja-jp/virtualization/windowscontainers/manage-docker/configure-docker-daemon" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/ja-jp/virtualization/windowscontainers/manage-docker/configure-docker-daemon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] Pyinstaller, Nuitka で作成した実行ファイルで GLIBC のエラーが発生する</title><link>https://blog.ponkotools.com/posts/2023/11/17/pyinstaller-nuitka/</link><pubDate>Fri, 17 Nov 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/11/17/pyinstaller-nuitka/</guid><description>&lt;p&gt;pyinstaller, nuitka で作成した実行ファイルを別のマシンで実行するとエラーが出て動きませんでした。&lt;/p&gt;
&lt;p&gt;具体的には以下のような GLIBC に関するエラーが表示されました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pyinstaller の場合&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10562&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt; &lt;span class="n"&gt;loading&lt;/span&gt; &lt;span class="n"&gt;Python&lt;/span&gt; &lt;span class="n"&gt;lib&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/home/username/dist/main/libpython3.11.so.1.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dlopen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;x86_64&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;gnu&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;libm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;so&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;GLIBC_2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; not found (required by /home/username/dist/main/libpython3.11.so.1.0)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Nuitka の場合&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./sample.bin: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33&amp;#39; not found (required by ./sample.bin)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./sample.bin: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34&amp;#39; not found (required by ./sample.bin)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./sample.bin: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.35&amp;#39; not found (required by /home/username/main.dist/libpython3.11.so.1.0)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./sample.bin: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33&amp;#39; not found (required by /home/username/main.dist/libpython3.11.so.1.0)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./sample.bin: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32&amp;#39; not found (required by /home/username/main.dist/libpython3.11.so.1.0)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./sample.bin: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34&amp;#39; not found (required by /home/username/main.dist/libpython3.11.so.1.0)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これの回避策は、サポートしたいシステムより古いシステムでビルドを行うことだそうです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://dev.to/k4ml/python-compile-standalone-executable-with-nuitka-1ml1" target="_blank" rel="noopener"
 &gt;https://dev.to/k4ml/python-compile-standalone-executable-with-nuitka-1ml1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/Nuitka/Nuitka/issues/1610" target="_blank" rel="noopener"
 &gt;https://github.com/Nuitka/Nuitka/issues/1610&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;私の場合、&lt;code&gt;python:3.11&lt;/code&gt; の Docker イメージを使ってビルドを行っていましたが、このイメージのディストリビューションは Debian 12 でした。
そこでビルドした成果物を Ubuntu 20.04 のマシンで動かすと上記のエラーが発生しました。&lt;/p&gt;
&lt;p&gt;なので、ビルドに使用する Docker イメージを &lt;code&gt;python:3.11-buster&lt;/code&gt; に変更したところ、エラーなく動作するようになりました。&lt;/p&gt;
&lt;p&gt;尚、&lt;code&gt;buster&lt;/code&gt; というのは Debian のコードネームのことで、Debian 10 のことだそうです。&lt;br&gt;
詳細は以下を参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.debian.org/releases/index.ja.html" target="_blank" rel="noopener"
 &gt;https://www.debian.org/releases/index.ja.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://dev.to/k4ml/python-compile-standalone-executable-with-nuitka-1ml1" target="_blank" rel="noopener"
 &gt;https://dev.to/k4ml/python-compile-standalone-executable-with-nuitka-1ml1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/Nuitka/Nuitka/issues/1610" target="_blank" rel="noopener"
 &gt;https://github.com/Nuitka/Nuitka/issues/1610&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.debian.org/releases/index.ja.html" target="_blank" rel="noopener"
 &gt;https://www.debian.org/releases/index.ja.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] docker-compose の --scale でコンテナを複製した際に、コンテナ側で何番目のコンテナなのかを判別したい</title><link>https://blog.ponkotools.com/posts/2023/11/14/docker/</link><pubDate>Tue, 14 Nov 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/11/14/docker/</guid><description>&lt;p&gt;本来、スケールは大きな負荷を処理できるようにするために使用し、スケールしたコンテナ毎に異なる構成を使用すべきではないと思いますが、それでも、スケールしたコンテナ毎にぞれぞれ別の構成が適用できると便利な場合もあります。
その場合、複製したコンテナ内で、自身が何番目のコンテナなのかを把握できるのが最も都合が良いと考えます。&lt;/p&gt;
&lt;p&gt;しかし、調べてみてもやり方が分からず、同様の質問はいくつか見つかりますが、現状、docker compose にはそのような機能は提供されていないようです。
その代わりに、docker swarm でタスクスロットを使うことで、コンテナの番号をコンテナ内に設定することができました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/commandline/service_create/" target="_blank" rel="noopener"
 &gt;https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/commandline/service_create/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプル"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;サンプル
&lt;/h2&gt;&lt;p&gt;以下のような docker-compose.yml を用意します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;version: &amp;#39;3&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;services:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; server:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; deploy:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; replicas: 3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; hostname: &amp;#34;server-{{.Task.Slot}}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下のコマンドでサービスを起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker swarm init # Swarmを初期化する（すでに初期化済みであれば不要）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack deploy -c docker-compose.yml my_stack
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;docker ps&lt;/code&gt; で確認すると、コンテナが3つ起動しているのが確認できます。&lt;br&gt;
ここで、3つのうちの1つのコンテナに入ってみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker exec -it &amp;lt;コンテナ名&amp;gt; bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コンテナ内で hostname を確認すると、番号が振られていることが確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# echo $(hostname)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;尚、サービスを停止するには、以下のコマンドを使用します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack rm my_stack
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/commandline/service_create/" target="_blank" rel="noopener"
 &gt;https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/commandline/service_create/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://forums.docker.com/t/how-to-identify-the-number-of-scaled-container/15041/11" target="_blank" rel="noopener"
 &gt;https://forums.docker.com/t/how-to-identify-the-number-of-scaled-container/15041/11&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/docker/compose/issues/9153" target="_blank" rel="noopener"
 &gt;https://github.com/docker/compose/issues/9153&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] pytest で motor のテストを行う</title><link>https://blog.ponkotools.com/posts/2023/11/13/python/</link><pubDate>Mon, 13 Nov 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/11/13/python/</guid><description>&lt;p&gt;MongoDB 用の非同期ライブラリに motor を使用しており、pytest でテストコードを記述する際にモックをどうすればいいか悩みました。&lt;/p&gt;
&lt;p&gt;当初は pymongo を使って同期的に使用していたため、MongoDB のモックには mongomock を使用していましたが、motor を使用する場合には mongomock-motor が使うとテストできました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://pypi.org/project/mongomock-motor/" target="_blank" rel="noopener"
 &gt;https://pypi.org/project/mongomock-motor/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="インストール"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;インストール
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install mongomock-motor
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;p&gt;上記のページにあるサンプルコードを pytest で実行する例です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pytest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mongomock_motor&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AsyncMongoMockClient&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@pytest.mark.asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_mock_client&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AsyncMongoMockClient&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;tests&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;test-1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert_one&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inserted_id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://pypi.org/project/mongomock-motor/" target="_blank" rel="noopener"
 &gt;https://pypi.org/project/mongomock-motor/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>シェルスクリプトで sudo 権限で実行されているどうかをチェックする</title><link>https://blog.ponkotools.com/posts/2023/11/12/linux/</link><pubDate>Sun, 12 Nov 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/11/12/linux/</guid><description>&lt;p&gt;&lt;code&gt;id -u&lt;/code&gt; コマンドを使用して実行ユーザーの UID（ユーザーID）を確認することでチェックできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# スクリプトをsudoで実行しているか確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;id -u&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -ne &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;このスクリプトはsudoで実行する必要があります。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;通常、root ユーザーの UID は 0 となります。&lt;/p&gt;</description></item><item><title>Rocket.Chat 移行後にアップロードファイルの URL が古いままになっている</title><link>https://blog.ponkotools.com/posts/2023/10/19/rocketchat/</link><pubDate>Thu, 19 Oct 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/10/19/rocketchat/</guid><description>&lt;p&gt;Rocket.Chat を移行したのですが、アップロード済みファイルの URL と、サイト URL のリセット値が、移行前の古い URL のままになっていました。&lt;/p&gt;
&lt;h2 id="概要"&gt;&lt;a href="#%e6%a6%82%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;概要
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Rocket.Chat を移行し、ドメイン (サイトURL) が変わった&lt;/li&gt;
&lt;li&gt;その際、Rocket.Chatを 3.10.14 から 6.2.12 にアップグレードしている
&lt;ul&gt;
&lt;li&gt;MongoDB も 4.0 から 5.0 にアップグレード&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Rocket.Chat 起動時に指定する環境変数 &lt;code&gt;ROOT_URL&lt;/code&gt; は移行後の URL を設定済み&lt;/li&gt;
&lt;li&gt;Rocket.Chat の管理者メニューで設定できる &lt;code&gt;サイト URL&lt;/code&gt; も移行後の URL を設定済み&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;この状況で、以下の２つの不具合を確認しました。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;アップロード済みのファイルの URL (ダウンロードリンク) が移行前の古い URL になっている&lt;/li&gt;
&lt;li&gt;Rocket.Chat の管理者メニューで設定できる &lt;code&gt;サイト URL&lt;/code&gt; について、リセットボタンを押すと移行前の古い URL がセットされる&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="先に結論"&gt;&lt;a href="#%e5%85%88%e3%81%ab%e7%b5%90%e8%ab%96" class="header-anchor"&gt;&lt;/a&gt;先に結論
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;1.&lt;/code&gt; については MongoDB のデータを直接修正すれば直りました。&lt;br&gt;
&lt;code&gt;2.&lt;/code&gt; については未解決です。&lt;/p&gt;
&lt;h3 id="mongodb-のデータを確認することにしたきっかけ"&gt;&lt;a href="#mongodb-%e3%81%ae%e3%83%87%e3%83%bc%e3%82%bf%e3%82%92%e7%a2%ba%e8%aa%8d%e3%81%99%e3%82%8b%e3%81%93%e3%81%a8%e3%81%ab%e3%81%97%e3%81%9f%e3%81%8d%e3%81%a3%e3%81%8b%e3%81%91" class="header-anchor"&gt;&lt;/a&gt;MongoDB のデータを確認することにしたきっかけ
&lt;/h3&gt;&lt;p&gt;いろいろググっていく中で以下のページに辿り着きました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.ryadel.com/en/rocket-chat-change-root_url-site-url-rocketchat/" target="_blank" rel="noopener"
 &gt;https://www.ryadel.com/en/rocket-chat-change-root_url-site-url-rocketchat/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;こちらの方法を試しても今回発生している不具合は直りませんでしたが、これをきっかけに MongoDB の中身を調査していくことで修正できました。&lt;/p&gt;
&lt;p&gt;MongoDB の中身の確認方法については以下が参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.mtioutput.com/entry/2019/02/21/180000" target="_blank" rel="noopener"
 &gt;https://www.mtioutput.com/entry/2019/02/21/180000&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://gihyo.jp/dev/serial/01/mongodb/0003" target="_blank" rel="noopener"
 &gt;https://gihyo.jp/dev/serial/01/mongodb/0003&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="調査の過程と修正方法"&gt;&lt;a href="#%e8%aa%bf%e6%9f%bb%e3%81%ae%e9%81%8e%e7%a8%8b%e3%81%a8%e4%bf%ae%e6%ad%a3%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;調査の過程と修正方法
&lt;/h2&gt;&lt;p&gt;Rocket.Chat と MongoDB は docker で動かしています。&lt;br&gt;
なので、まず MongoDB の docker コンテナに入ります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker &lt;span class="nb"&gt;exec&lt;/span&gt; -it rocketchat-mongo bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コンテナに入ったら MongoDB シェルを開き、&lt;code&gt;rocketchat&lt;/code&gt; のデータベースを選択します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# mongo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; use rocketchat
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コレクションを表示してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; show collections
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;たくさん表示されますが、ここから不具合内容に該当する箇所を推測して調査していきます。&lt;/p&gt;
&lt;h2 id="1-アップロードファイルのダウンロードリンクについて"&gt;&lt;a href="#1-%e3%82%a2%e3%83%83%e3%83%97%e3%83%ad%e3%83%bc%e3%83%89%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ae%e3%83%80%e3%82%a6%e3%83%b3%e3%83%ad%e3%83%bc%e3%83%89%e3%83%aa%e3%83%b3%e3%82%af%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6" class="header-anchor"&gt;&lt;/a&gt;1. アップロードファイルのダウンロードリンクについて
&lt;/h2&gt;&lt;p&gt;前述の &lt;code&gt;1.&lt;/code&gt; についてですが、こちらはアップロードファイルに関することなので、&lt;code&gt;rocketchat_uploads&lt;/code&gt; の中身を表示してみました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; db.rocketchat_uploads.find&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;20件のみ表示されますが、適当なデータ一件について中身をみると以下のような感じになっていました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;27JzjqpXHxAHBzaxp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;hoge.jpg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;51268&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;image/jpeg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;rid&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;MgKrXXN4XmQwtMMjgjXnWzpNvR6YrRpH4F&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;userId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;jXnWzpNvR6YrRpH4F&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;store&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;GridFS:Uploads&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;_updatedAt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;ISODate(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2023-07-26T03:58:50.233Z&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;instanceId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;R252ARSHBKR3RrXHY&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;identify&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;format&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;jpeg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;width&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;495&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;height&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;700&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;complete&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;etag&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;HoMjiYj2fbb799RFK&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/ufs/GridFS:Uploads/27JzjqpXHxAHBzaxp/%E5%90%8D%E7%A7%B0%E6%9C%AA%E8%A8%AD%E5%AE%9A%201.jpg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;progress&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;token&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;68c8A8CAb8&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;uploadedAt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;ISODate(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2023-07-26T03:58:50.852Z&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;uploading&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;http://old_domain:port/ufs/GridFS:Uploads/27JzjqpXHxAHBzaxp/%E5%90%8D%E7%A7%B0%E6%9C%AA%E8%A8%AD%E5%AE%9A%201.jpg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;typeGroup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;image&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;見てわかる通り、&lt;code&gt;url&lt;/code&gt; のフィールドにファイルへの絶対パスが記録されているため、これを修正しないと直らないんじゃないかと思いました。&lt;/p&gt;
&lt;p&gt;というわけで、以下のコマンドでドメインの部分のみを置換します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;db.rocketchat_uploads.find&lt;span class="o"&gt;()&lt;/span&gt;.forEach&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;row&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; row.url &lt;span class="o"&gt;=&lt;/span&gt; row.url.replace&lt;span class="o"&gt;(&lt;/span&gt;new RegExp&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;old_domain&amp;#34;&lt;/span&gt;, &lt;span class="s1"&gt;&amp;#39;g&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;new_domain&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; db.rocketchat_uploads.save&lt;span class="o"&gt;(&lt;/span&gt;row&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで Rocket.Chat のほうを確認すると、URL が直っていました。&lt;/p&gt;
&lt;h2 id="2-サイト-url-のリセット値について"&gt;&lt;a href="#2-%e3%82%b5%e3%82%a4%e3%83%88-url-%e3%81%ae%e3%83%aa%e3%82%bb%e3%83%83%e3%83%88%e5%80%a4%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6" class="header-anchor"&gt;&lt;/a&gt;2. サイト URL` のリセット値について
&lt;/h2&gt;&lt;p&gt;次に前述の &lt;code&gt;2.&lt;/code&gt; についてですが、設定に関することなので &lt;code&gt;rocketchat_settings&lt;/code&gt; を確認してみました。
こちらはついては中身を全てを見たかったので、以下のようにして json ファイルに出力して確認しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mongoexport -d rocketchat -c rocketchat_settings -o rocketchat_settings.json --type&lt;span class="o"&gt;=&lt;/span&gt;json mongodb://localhost:27017
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;で、中身を確認してみましたが、それらしい設定は見当たりませんでした。&lt;br&gt;
他のコレクションもいろいろ確認してみましたが、それらしい設定は見つかっていません。&lt;/p&gt;
&lt;p&gt;というわけで未解決ですが、特に実害はないので放っておいてます。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.ryadel.com/en/rocket-chat-change-root_url-site-url-rocketchat/" target="_blank" rel="noopener"
 &gt;https://www.ryadel.com/en/rocket-chat-change-root_url-site-url-rocketchat/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.mtioutput.com/entry/2019/02/21/180000" target="_blank" rel="noopener"
 &gt;https://www.mtioutput.com/entry/2019/02/21/180000&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://gihyo.jp/dev/serial/01/mongodb/0003" target="_blank" rel="noopener"
 &gt;https://gihyo.jp/dev/serial/01/mongodb/0003&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Rocket.Chat のアップグレード手順</title><link>https://blog.ponkotools.com/posts/2023/10/11/rocketchat/</link><pubDate>Wed, 11 Oct 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/10/11/rocketchat/</guid><description>&lt;p&gt;アップグレード手順については以下に記載されています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.rocket.chat/deploy/deploy-rocket.chat/updating-rocket.chat" target="_blank" rel="noopener"
 &gt;https://docs.rocket.chat/deploy/deploy-rocket.chat/updating-rocket.chat&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;アップグレードのフローが以下になります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://whimsical.com/upgrade-version-path-rocket-chat-51eoS7aUunTan5wLt2CBHU" target="_blank" rel="noopener"
 &gt;https://whimsical.com/upgrade-version-path-rocket-chat-51eoS7aUunTan5wLt2CBHU&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これに従ってアップデートしますが、いくつかはまったポイントがありました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;p&gt;アップグレード前のバージョンは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rocket.Chat Version: 3.10.4&lt;/li&gt;
&lt;li&gt;NodeJS Version: 12.18.4 - x64&lt;/li&gt;
&lt;li&gt;MongoDB Version: 4.0.28&lt;/li&gt;
&lt;li&gt;MongoDB Engine: wiredTiger&lt;/li&gt;
&lt;li&gt;Platform: linux&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Rocket.Chat も MongoDB も docker で動かしています。&lt;/p&gt;
&lt;h2 id="rocketchat-3187-へのアップグレード"&gt;&lt;a href="#rocketchat-3187-%e3%81%b8%e3%81%ae%e3%82%a2%e3%83%83%e3%83%97%e3%82%b0%e3%83%ac%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;Rocket.Chat 3.18.7 へのアップグレード
&lt;/h2&gt;&lt;p&gt;現在のバージョンが 3.10.4 なので、3系の最新の 3.18.7 にアップグレードしました。&lt;br&gt;
すると、データベースバージョンのエラーが表示されたました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+----------------------------------------------------------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; ERROR! SERVER STOPPED &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; Your database migration failed: &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; Start date cannot be later than expire date &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; Please make sure you are running the latest version and try again. &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; If the problem persists, please contact support. &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; This Rocket.Chat version: 3.18.7 &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; Database locked at version: &lt;span class="m"&gt;213&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; Database target version: &lt;span class="m"&gt;232&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; Commit: 660c9f5e896982932e1d02d35ddd6013c6b03e11 &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; Date: Mon May &lt;span class="m"&gt;30&lt;/span&gt; 19:06:57 &lt;span class="m"&gt;2022&lt;/span&gt; -0300 &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; Branch: HEAD &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; Tag: 3.18.7 &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+----------------------------------------------------------------------+
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;対策は以下に書いてありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://martinschoeler.github.io/docs/administrator-guides/database-migration/" target="_blank" rel="noopener"
 &gt;https://martinschoeler.github.io/docs/administrator-guides/database-migration/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MongoDB のコンテナに入り、以下のコマンドを実行してバージョンを強制的に一つ上げます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# mongo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; use rocketchat
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; db.migrations.update({_id: &amp;#39;control&amp;#39;},{$set:{locked:false,version:231}})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで Rocket.Chat を再起動すれば OK でした。&lt;/p&gt;
&lt;h2 id="rocketchat-3187-から-487-へのアップグレード"&gt;&lt;a href="#rocketchat-3187-%e3%81%8b%e3%82%89-487-%e3%81%b8%e3%81%ae%e3%82%a2%e3%83%83%e3%83%97%e3%82%b0%e3%83%ac%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;Rocket.Chat 3.18.7 から 4.8.7 へのアップグレード
&lt;/h2&gt;&lt;p&gt;次に4系の最新の 4.8.7 にアップグレードしました。&lt;br&gt;
これはすんなりいきました。&lt;/p&gt;
&lt;h2 id="mongodb-のアップグレード"&gt;&lt;a href="#mongodb-%e3%81%ae%e3%82%a2%e3%83%83%e3%83%97%e3%82%b0%e3%83%ac%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;MongoDB のアップグレード
&lt;/h2&gt;&lt;p&gt;上記のフローによれば、Rocket.Chat を5系にアップグレードする前に、MongoDB を 5.0 以上までアップグレードする必要があります。&lt;br&gt;
方法については以下に記載されています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.growi.org/ja/admin-guide/admin-cookbook/upgrade-mongodb.html" target="_blank" rel="noopener"
 &gt;https://docs.growi.org/ja/admin-guide/admin-cookbook/upgrade-mongodb.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mongodb-40-から-42-へのアップグレード"&gt;&lt;a href="#mongodb-40-%e3%81%8b%e3%82%89-42-%e3%81%b8%e3%81%ae%e3%82%a2%e3%83%83%e3%83%97%e3%82%b0%e3%83%ac%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;MongoDB 4.0 から 4.2 へのアップグレード
&lt;/h3&gt;&lt;p&gt;現在のバージョンが 4.0 なので、まずは 4.2 にアップグレードしました。
これはすんなりいきました。&lt;/p&gt;
&lt;h3 id="mongodb-42-から-44-へのアップグレード"&gt;&lt;a href="#mongodb-42-%e3%81%8b%e3%82%89-44-%e3%81%b8%e3%81%ae%e3%82%a2%e3%83%83%e3%83%97%e3%82%b0%e3%83%ac%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;MongoDB 4.2 から 4.4 へのアップグレード
&lt;/h3&gt;&lt;p&gt;次に 4.4 にアップグレードしたところ、以下のようなエラーとなりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{&amp;#34;t&amp;#34;:{&amp;#34;$date&amp;#34;:&amp;#34;2023-10-13T00:38:13.842+00:00&amp;#34;},&amp;#34;s&amp;#34;:&amp;#34;W&amp;#34;, &amp;#34;c&amp;#34;:&amp;#34;STORAGE&amp;#34;, &amp;#34;id&amp;#34;:22347, &amp;#34;ctx&amp;#34;:&amp;#34;initandlisten&amp;#34;,&amp;#34;msg&amp;#34;:&amp;#34;Failed to start up WiredTiger under any compatibility version. This may be due to an unsupported upgrade or downgrade.&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{&amp;#34;t&amp;#34;:{&amp;#34;$date&amp;#34;:&amp;#34;2023-10-13T00:38:13.842+00:00&amp;#34;},&amp;#34;s&amp;#34;:&amp;#34;F&amp;#34;, &amp;#34;c&amp;#34;:&amp;#34;STORAGE&amp;#34;, &amp;#34;id&amp;#34;:28595, &amp;#34;ctx&amp;#34;:&amp;#34;initandlisten&amp;#34;,&amp;#34;msg&amp;#34;:&amp;#34;Terminating.&amp;#34;,&amp;#34;attr&amp;#34;:{&amp;#34;reason&amp;#34;:&amp;#34;95: Operation not supported&amp;#34;}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{&amp;#34;t&amp;#34;:{&amp;#34;$date&amp;#34;:&amp;#34;2023-10-13T00:38:13.842+00:00&amp;#34;},&amp;#34;s&amp;#34;:&amp;#34;F&amp;#34;, &amp;#34;c&amp;#34;:&amp;#34;-&amp;#34;, &amp;#34;id&amp;#34;:23091, &amp;#34;ctx&amp;#34;:&amp;#34;initandlisten&amp;#34;,&amp;#34;msg&amp;#34;:&amp;#34;Fatal assertion&amp;#34;,&amp;#34;attr&amp;#34;:{&amp;#34;msgid&amp;#34;:28595,&amp;#34;file&amp;#34;:&amp;#34;src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp&amp;#34;,&amp;#34;line&amp;#34;:958}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{&amp;#34;t&amp;#34;:{&amp;#34;$date&amp;#34;:&amp;#34;2023-10-13T00:38:13.843+00:00&amp;#34;},&amp;#34;s&amp;#34;:&amp;#34;F&amp;#34;, &amp;#34;c&amp;#34;:&amp;#34;-&amp;#34;, &amp;#34;id&amp;#34;:23092, &amp;#34;ctx&amp;#34;:&amp;#34;initandlisten&amp;#34;,&amp;#34;msg&amp;#34;:&amp;#34;\n\n***aborting after fassert() failure\n\n&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;MongoDB を 4.2 に戻してコンテナに入り、以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# mongo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; db.adminCommand( { setFeatureCompatibilityVersion: &amp;#34;4.2&amp;#34; } )
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで Rocket.Chat を再起動すれば OK でした。&lt;/p&gt;
&lt;h3 id="mongodb-44-から-50-へのアップグレード"&gt;&lt;a href="#mongodb-44-%e3%81%8b%e3%82%89-50-%e3%81%b8%e3%81%ae%e3%82%a2%e3%83%83%e3%83%97%e3%82%b0%e3%83%ac%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;MongoDB 4.4 から 5.0 へのアップグレード
&lt;/h3&gt;&lt;p&gt;次に 5.0 にアップグレードしたところ、同様のエラーとなりました。&lt;br&gt;
MongoDB を 4.4 に戻してコンテナに入り、以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# mongo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; db.adminCommand( { setFeatureCompatibilityVersion: &amp;#34;4.4&amp;#34; } )
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで Rocket.Chat を再起動すれば OK でした。&lt;/p&gt;
&lt;h2 id="rocketchat-487-から-5410-へのアップグレード"&gt;&lt;a href="#rocketchat-487-%e3%81%8b%e3%82%89-5410-%e3%81%b8%e3%81%ae%e3%82%a2%e3%83%83%e3%83%97%e3%82%b0%e3%83%ac%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;Rocket.Chat 4.8.7 から 5.4.10 へのアップグレード
&lt;/h2&gt;&lt;p&gt;MongoDB を 5.0 までアップグレードしたので、次は Rocket.Chat を5系の最新の 5.4.10 にアップグレードしました。&lt;br&gt;
すると以下のエラーが表示されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/app/bundle/programs/server/node_modules/fibers/future.js:313
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; throw(ex);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Timeout._onTimeout (/app/bundle/programs/server/npm/node_modules/meteor/npm-mongo/node_modules/mongodb/lib/sdam/topology.js:312:38)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at listOnTimeout (internal/timers.js:557:17)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at processTimers (internal/timers.js:500:7) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; reason: TopologyDescription {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; type: &amp;#39;ReplicaSetNoPrimary&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; servers: Map(1) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#39;localhost:27017&amp;#39; =&amp;gt; ServerDescription {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; _hostAddress: HostAddress { isIPv6: false, host: &amp;#39;localhost&amp;#39;, port: 27017 },
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; address: &amp;#39;localhost:27017&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; type: &amp;#39;Unknown&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; hosts: [],
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; passives: [],
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; arbiters: [],
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; tags: {},
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; minWireVersion: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; maxWireVersion: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; roundTripTime: -1,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lastUpdateTime: 17764280,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lastWriteDate: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; error: MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at connectionFailureError (/app/bundle/programs/server/npm/node_modules/meteor/npm-mongo/node_modules/mongodb/lib/cmap/connect.js:381:20)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Socket.&amp;lt;anonymous&amp;gt; (/app/bundle/programs/server/npm/node_modules/meteor/npm-mongo/node_modules/mongodb/lib/cmap/connect.js:301:22)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Object.onceWrapper (events.js:520:26)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Socket.emit (events.js:400:28)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at emitErrorNT (internal/streams/destroy.js:106:8)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at emitErrorCloseNT (internal/streams/destroy.js:74:3)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at processTicksAndRejections (internal/process/task_queues.js:82:21)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; stale: false,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; compatible: true,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; heartbeatFrequencyMS: 10000,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; localThresholdMS: 15,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; setName: &amp;#39;rs0&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; maxSetVersion: 2,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; maxElectionId: ObjectId {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; [Symbol(id)]: Buffer(12) [Uint8Array] [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 127, 255, 255, 255, 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 0, 0, 0, 0, 0,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 0, 10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; commonWireVersion: 13,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; logicalSessionTimeoutMinutes: undefined
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;解決策は以下にありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/RocketChat/Rocket.Chat/releases/tag/5.0.0" target="_blank" rel="noopener"
 &gt;https://github.com/RocketChat/Rocket.Chat/releases/tag/5.0.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;環境変数 &lt;code&gt;MONGO_URL&lt;/code&gt; &lt;code&gt;MONGO_OPLOG_URL&lt;/code&gt; に &lt;code&gt;directConnection=true&lt;/code&gt; を追加します。&lt;br&gt;
例えば、&lt;code&gt;MONGO_URL=mongodb://mongo/rocketchat?replicaSet=rs0&amp;amp;directConnection=true&lt;/code&gt; のような感じです。&lt;/p&gt;
&lt;p&gt;これで Rocket.Chat を再起動すれば OK でした。&lt;/p&gt;
&lt;h2 id="rocketchat-を最新にアップデート"&gt;&lt;a href="#rocketchat-%e3%82%92%e6%9c%80%e6%96%b0%e3%81%ab%e3%82%a2%e3%83%83%e3%83%97%e3%83%87%e3%83%bc%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;Rocket.Chat を最新にアップデート
&lt;/h2&gt;&lt;p&gt;最後に、Rocket.Chat を現在の最新バージョンである 6.3.9 にアップグレードしました。
以上で完了です。&lt;/p&gt;</description></item><item><title>[Python] OS の時刻（システムクロック）に影響を受けないように時間の計測を行う</title><link>https://blog.ponkotools.com/posts/2023/09/08/python/</link><pubDate>Fri, 08 Sep 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/09/08/python/</guid><description>&lt;p&gt;&lt;code&gt;time.monotonic()&lt;/code&gt; を使えば OK です。&lt;/p&gt;
&lt;p&gt;元々、以下の様に &lt;code&gt;time.time()&lt;/code&gt; を使って処理時間の計測を行っていたのですが、この場合、計測途中でシステムクロックが変更されてしまうと、計測時間も影響を受けてしまいます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# この間にシステムクロックが変更されると計測時間にも影響を与える&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;elapsed_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 過去に戻ると負の値に、未来に行くと大きな値になってしまう&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elapsed_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;time.monotonic()&lt;/code&gt; を使えばシステムクロックの影響を受けないので、純粋に処理にかかった実時間を計測できます。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.python.org/ja/3.10/library/time.html#time.monotonic" target="_blank" rel="noopener"
 &gt;https://docs.python.org/ja/3.10/library/time.html#time.monotonic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>YAML のアンカー/エイリアスと docker compose の profiles を使って docker-compose.yml を作成する</title><link>https://blog.ponkotools.com/posts/2023/08/25/yaml/</link><pubDate>Fri, 25 Aug 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/08/25/yaml/</guid><description>&lt;p&gt;github などで公開されている docker-compose.yml を見ていると、見慣れない表記を見かけることがあり、調べてみると YAML のアンカー/エイリアス機能であることがわかりました。&lt;/p&gt;
&lt;p&gt;これと、docker compose の &lt;code&gt;--profiles&lt;/code&gt; を組み合わせて、&lt;code&gt;docker-compose.yml&lt;/code&gt; 一つで様々な環境で動かすことができるようにしているのを見るととても便利だなと思ったので、メモしておきます。&lt;/p&gt;
&lt;h2 id="yaml-のアンカーとエイリアス"&gt;&lt;a href="#yaml-%e3%81%ae%e3%82%a2%e3%83%b3%e3%82%ab%e3%83%bc%e3%81%a8%e3%82%a8%e3%82%a4%e3%83%aa%e3%82%a2%e3%82%b9" class="header-anchor"&gt;&lt;/a&gt;yaml のアンカーとエイリアス
&lt;/h2&gt;&lt;p&gt;yaml 自体の標準機能です。&lt;br&gt;
これを使うことで、記述内容を共通化して DRY にできます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;アンカー: &lt;code&gt;&amp;amp;&lt;/code&gt; を付けることで、他の場所でも参照できるようにします。&lt;/li&gt;
&lt;li&gt;エイリアス: &lt;code&gt;*&lt;/code&gt; を付けて、アンカーで定義した内容を参照します。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;サンプル1&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;aaa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;&amp;amp;hoge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1111&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2222&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;ddd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;*hoge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上記の場合、以下の様に展開されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;aaa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1111&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2222&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;ddd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1111&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2222&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;サンプル2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;アンカー内にアンカーがあっても問題ありません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;aaa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;&amp;amp;hoge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1111&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;&amp;amp;piyo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2222&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;ddd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;*hoge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;eee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;*piyo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上記の場合、以下の様に展開されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;aaa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1111&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2222&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;ddd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1111&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2222&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;eee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2222&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="マージ"&gt;&lt;a href="#%e3%83%9e%e3%83%bc%e3%82%b8" class="header-anchor"&gt;&lt;/a&gt;マージ
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;&amp;lt;&amp;lt;:&lt;/code&gt; と記述することで、アンカーで定義した内容をそのまま入れ込むことができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;aaa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;&amp;amp;hoge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1111&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2222&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;ddd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;*hoge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;eee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3333&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上記の場合、以下の様に展開されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;aaa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1111&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2222&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;ddd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1111&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2222&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;eee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3333&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="アンカーの上書き"&gt;&lt;a href="#%e3%82%a2%e3%83%b3%e3%82%ab%e3%83%bc%e3%81%ae%e4%b8%8a%e6%9b%b8%e3%81%8d" class="header-anchor"&gt;&lt;/a&gt;アンカーの上書き
&lt;/h3&gt;&lt;p&gt;アンカー名と同じキーが後にあった場合、上書きされます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;aaa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;&amp;amp;hoge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1111&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2222&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ddd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3333&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;eee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;*hoge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4444&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;fff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;*hoge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ddd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5555&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上記は以下のように展開されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;aaa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1111&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2222&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ddd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3333&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;eee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4444&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2222&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ddd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3333&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;fff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1111&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2222&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ddd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5555&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これを使って、内容の大部分を共通化しつつ一部分だけは変えたいということができます。&lt;/p&gt;
&lt;h3 id="docker-composeyml-で使用する場合"&gt;&lt;a href="#docker-composeyml-%e3%81%a7%e4%bd%bf%e7%94%a8%e3%81%99%e3%82%8b%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;docker-compose.yml で使用する場合
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt; 内で共通の設定を括りだそうと以下の様に書くとエラーになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;common: &amp;amp;common
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: hoge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; app:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;&amp;lt;: *common
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;docker compose によって &lt;code&gt;common&lt;/code&gt; 自体が解釈されるためです。&lt;br&gt;
この場合、プレフィックスとして &lt;code&gt;x-&lt;/code&gt; を付けると、docker compose からは無視されるようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;x-common: &amp;amp;common
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: hoge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; app:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;&amp;lt;: *x-common
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="docker-compose-の-profile"&gt;&lt;a href="#docker-compose-%e3%81%ae-profile" class="header-anchor"&gt;&lt;/a&gt;docker compose の profile
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt; で定義されたサービスに profiles を定義することで、サービスのグループ分けやタグ付けのようなことができます。&lt;br&gt;
以下が公式ドキュメントによる説明です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.jp/compose/profiles.html" target="_blank" rel="noopener"
 &gt;https://docs.docker.jp/compose/profiles.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;profiles で指定したサービスのみを起動させることができるようになります。&lt;/p&gt;
&lt;h2 id="上記を踏まえた実用的なサンプル"&gt;&lt;a href="#%e4%b8%8a%e8%a8%98%e3%82%92%e8%b8%8f%e3%81%be%e3%81%88%e3%81%9f%e5%ae%9f%e7%94%a8%e7%9a%84%e3%81%aa%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;上記を踏まえた実用的なサンプル
&lt;/h2&gt;&lt;p&gt;上記を踏まえると、yaml のアンカー/エイリアスにより記述内容を共通化しつつ、profile によって起動するコンテナを切り替えることができます。&lt;/p&gt;
&lt;p&gt;尚、今回の記事を書くことになった動機が、以下の Stable Diffusion 用の docker-compose.yml を見たときで、どういう意味なんだろうと思ったのがきっかけです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/AbdBarho/stable-diffusion-webui-docker" target="_blank" rel="noopener"
 &gt;https://github.com/AbdBarho/stable-diffusion-webui-docker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;GPU を使う場合と、CPU を使う場合とで上手く共通化されており、また記述量も少なくサンプルとして丁度いいので、こちらをサンプルとして挙げさせていただきます。&lt;/p&gt;
&lt;h2 id="docker-composeyml-の確認"&gt;&lt;a href="#docker-composeyml-%e3%81%ae%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;docker-compose.yml の確認
&lt;/h2&gt;&lt;p&gt;ちなみに、docker compose によってどのように yaml ファイルが読み込まれるか確認するには、config オプションを使用します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker compose config
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://genzouw.com/entry/2021/06/19/082626/2661/#" target="_blank" rel="noopener"
 &gt;https://genzouw.com/entry/2021/06/19/082626/2661/#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.jp/compose/profiles.html" target="_blank" rel="noopener"
 &gt;https://docs.docker.jp/compose/profiles.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://techracho.bpsinc.jp/hachi8833/2020_02_07/87447" target="_blank" rel="noopener"
 &gt;https://techracho.bpsinc.jp/hachi8833/2020_02_07/87447&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>`ImportError: cannot import name '_compare_version' from 'torchmetrics.utilities.imports'` のエラーが出る</title><link>https://blog.ponkotools.com/posts/2023/08/21/stable-diffusion/</link><pubDate>Mon, 21 Aug 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/08/21/stable-diffusion/</guid><description>&lt;p&gt;Stable Diffusion を動かそうとして以下のエラーが出ました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ImportError: cannot import name &amp;#39;_compare_version&amp;#39; from &amp;#39;torchmetrics.utilities.imports&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(/usr/local/lib/python3.8/site-packages/torchmetrics/utilities/imports.py)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下に対策が載っており、&lt;code&gt;torchmetrics&lt;/code&gt; を &lt;code&gt;0.11.4&lt;/code&gt; にダウングレードすれば解決しました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/11648" target="_blank" rel="noopener"
 &gt;https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/11648&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pip install torchmetrics==0.11.4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/11648" target="_blank" rel="noopener"
 &gt;https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/11648&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[VSCode] Markdown Preview Enhanced で HTML 出力する際にサイドバーの目次を入れる</title><link>https://blog.ponkotools.com/posts/2023/07/20/markdown-preview-enhanced/</link><pubDate>Thu, 20 Jul 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/07/20/markdown-preview-enhanced/</guid><description>&lt;p&gt;ずっとやり方が分からなかったのですが、英語版のマニュアルにやり方が書いてありました。&lt;/p&gt;
&lt;p&gt;サイドバーのTOCを生成するには、VSCode の Markdown Preview Enhanced の設定でスクリプトの実行を有効にする必要があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://shd101wyy.github.io/markdown-preview-enhanced/#/html?id=configuration" target="_blank" rel="noopener"
 &gt;https://shd101wyy.github.io/markdown-preview-enhanced/#/html?id=configuration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;尚、上記の情報は現時点の日本語版のマニュアルには書いてありませんでした。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://shd101wyy.github.io/markdown-preview-enhanced/#/ja-jp/html?id=%e8%a8%ad%e5%ae%9a" target="_blank" rel="noopener"
 &gt;https://shd101wyy.github.io/markdown-preview-enhanced/#/ja-jp/html?id=%e8%a8%ad%e5%ae%9a&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;VSCode 1.80.1&lt;/li&gt;
&lt;li&gt;Markdown Preview Enhanced v0.6.8&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="スクリプトの実行を有効にする"&gt;&lt;a href="#%e3%82%b9%e3%82%af%e3%83%aa%e3%83%97%e3%83%88%e3%81%ae%e5%ae%9f%e8%a1%8c%e3%82%92%e6%9c%89%e5%8a%b9%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;スクリプトの実行を有効にする
&lt;/h2&gt;&lt;p&gt;拡張機能の設定で &lt;code&gt;enableScriptExecution&lt;/code&gt; で検索すると設定項目が表示されるのでチェックを入れます。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="681px" data-flex-grow="284" height="245" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2023/07/20/markdown-preview-enhanced/01.png" width="696"&gt;&lt;/p&gt;
&lt;p&gt;尚、有効にするとセキュリティリスクがありますので、その点ご注意ください。&lt;/p&gt;
&lt;h2 id="html-の出力"&gt;&lt;a href="#html-%e3%81%ae%e5%87%ba%e5%8a%9b" class="header-anchor"&gt;&lt;/a&gt;html の出力
&lt;/h2&gt;&lt;p&gt;あとはマークダウンのプレビュー画面で右クリックし、HTML に出力するだけでサイドバーに目次が出力されます。&lt;br&gt;
尚、デフォルトではサイドバーは閉じた状態となっていました。&lt;br&gt;
マークダウン内に &lt;code&gt;toc: true&lt;/code&gt; を記述すると、サイドバーが開いた状態となりました。&lt;/p&gt;
&lt;p&gt;以下サンプルです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;html:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; toc: true
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 見出し1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;## 見出し2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;### 見出し3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;### 見出し3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 見出し1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;## 見出し2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="307px" data-flex-grow="128" height="552" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2023/07/20/markdown-preview-enhanced/02.png" width="707"&gt;&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://shd101wyy.github.io/markdown-preview-enhanced/#/html?id=configuration" target="_blank" rel="noopener"
 &gt;https://shd101wyy.github.io/markdown-preview-enhanced/#/html?id=configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/kumapo0313/items/a59df3d74a7eaaaf3137" target="_blank" rel="noopener"
 &gt;https://qiita.com/kumapo0313/items/a59df3d74a7eaaaf3137&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>WSL でディストリビューションを削除して再インストール後に起動エラーになる</title><link>https://blog.ponkotools.com/posts/2023/07/14/wsl/</link><pubDate>Fri, 14 Jul 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/07/14/wsl/</guid><description>&lt;p&gt;スタートメニューから Ubuntu 20.04 をアンインストールして、再度 MS ストアからインストールして起動しようとしたら以下のエラーが表示されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ps" data-lang="ps"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;Error&lt;/span&gt; &lt;span class="nf"&gt;code:&lt;/span&gt; &lt;span class="nf"&gt;Wsl&lt;/span&gt;&lt;span class="nv"&gt;/Service/CreateInstance/MountVhd/ERROR_FILE_NOT_FOUND&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;まず、インストールされているディストリビューションを確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ps" data-lang="ps"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;wsl&lt;/span&gt; &lt;span class="nf"&gt;-l&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;Linux&lt;/span&gt; &lt;span class="nf"&gt;用&lt;/span&gt; &lt;span class="nf"&gt;Windows&lt;/span&gt; &lt;span class="nf"&gt;サブシステム&lt;/span&gt; &lt;span class="nf"&gt;ディストリビューション:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;Ubuntu-20.04&lt;/span&gt; &lt;span class="s"&gt;(既定)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;アンインストールしたはずのディストリビューションが残っていると思うので、以下のコマンドで登録を解除します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ps" data-lang="ps"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;wsl&lt;/span&gt; &lt;span class="nf"&gt;--unregister&lt;/span&gt; &lt;span class="nf"&gt;Ubuntu-20.04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで、再度ディストリビューションを起動すれば OK です。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.techgaku.com/fix-ubuntu-boot-error-on-wsl-after-reinstall/" target="_blank" rel="noopener"
 &gt;https://www.techgaku.com/fix-ubuntu-boot-error-on-wsl-after-reinstall/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Microsoft ストア版の WSL をインストールする</title><link>https://blog.ponkotools.com/posts/2023/07/06/wsl/</link><pubDate>Thu, 06 Jul 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/07/06/wsl/</guid><description>&lt;p&gt;WSL について、Windows のコンポーネント（組み込み）として提供されているものと、Microsoft Store で提供されているものがあるのを知りました。&lt;/p&gt;
&lt;p&gt;きっかけは、WSL2 上の Ubuntu で systemd を使おうとしたら使えなかったことで、調べていくと WSL 自体のバージョンが 0.67.6 以降だと systemd が使えることがわかりました。&lt;/p&gt;
&lt;p&gt;WSL 自体のバージョンは以下のコマンドで確認できるらしいのですが、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ps" data-lang="ps"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;wsl&lt;/span&gt; &lt;span class="nf"&gt;--version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;私の環境ではバージョンが表示されず、コマンドの説明が表示されてしまいました。&lt;/p&gt;
&lt;p&gt;これは、どうやら WSL のバージョンが古いのが原因らしく、最新版は Microsoft Store からインストールできるらしいと。&lt;br&gt;
ここで、2022年11月に正式版としてリリースされたストア版の WSL を知り、自分が使っていたのは「Windows の機能の有効化または無効化」からインストールしたコンポーネント版で、古いプレビュー版の WSL だということを知りました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/omu_kato/items/f9a6b5a02e25f5f2a487" target="_blank" rel="noopener"
 &gt;https://qiita.com/omu_kato/items/f9a6b5a02e25f5f2a487&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ストア版の WSL は普通に Microsoft Store で検索すれば見つかるので、そこでインストールするだけです。&lt;/p&gt;
&lt;p&gt;尚、既にコンポーネント版を使っていてもストア版をインストールして使えるようですが、私の環境では Ubuntu 22.04 を起動しようとすると &lt;code&gt;Error code: Wsl/Service/CreateInstance/MountVhd/ERROR_FILE_NOT_FOUND&lt;/code&gt; のエラーが出てしまいました。&lt;/p&gt;
&lt;p&gt;これについては、以下を参考に WSL から Ubuntu 22.04 の登録を解除すれば直りました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.techgaku.com/fix-ubuntu-boot-error-on-wsl-after-reinstall/" target="_blank" rel="noopener"
 &gt;https://www.techgaku.com/fix-ubuntu-boot-error-on-wsl-after-reinstall/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/omu_kato/items/f9a6b5a02e25f5f2a487" target="_blank" rel="noopener"
 &gt;https://qiita.com/omu_kato/items/f9a6b5a02e25f5f2a487&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/hiromasa-masuda/items/355fe0c882a1a0abe1e1" target="_blank" rel="noopener"
 &gt;https://qiita.com/hiromasa-masuda/items/355fe0c882a1a0abe1e1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.techgaku.com/fix-ubuntu-boot-error-on-wsl-after-reinstall/" target="_blank" rel="noopener"
 &gt;https://www.techgaku.com/fix-ubuntu-boot-error-on-wsl-after-reinstall/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>EasyTAG 2.4.3 で画像がある場合に mp3 ファイルのタグ書き込みに失敗する</title><link>https://blog.ponkotools.com/posts/2023/07/02/easytag/</link><pubDate>Sun, 02 Jul 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/07/02/easytag/</guid><description>&lt;p&gt;Windows で EasyTAG 2.4.3 の場合に発生します。&lt;/p&gt;
&lt;p&gt;いろいろ試しても上手くいかず悩んでいたのですが、以下に報告が上がっていました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gitlab.gnome.org/GNOME/easytag/-/issues/5" target="_blank" rel="noopener"
 &gt;https://gitlab.gnome.org/GNOME/easytag/-/issues/5&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2.4.2 にダウングレードすると問題なく書き込めました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gitlab.gnome.org/GNOME/easytag/-/issues/5" target="_blank" rel="noopener"
 &gt;https://gitlab.gnome.org/GNOME/easytag/-/issues/5&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>systemd で環境変数を展開する</title><link>https://blog.ponkotools.com/posts/2023/06/14/systemd/</link><pubDate>Wed, 14 Jun 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/06/14/systemd/</guid><description>&lt;p&gt;環境変数を参照する Python アプリを systemd でサービス化したときにかなりはまってしまいました。&lt;/p&gt;
&lt;p&gt;systemd はユーザーの環境変数を参照しないようなので、ユニット定義ファイルで環境変数を設定する必要があるそうで、&lt;code&gt;Environment&lt;/code&gt; で記述したり、外部ファイルに定義して &lt;code&gt;EnvironmentFile&lt;/code&gt; で読み込む方法があるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://note.com/meiburg/n/n5cd098a8c744" target="_blank" rel="noopener"
 &gt;https://note.com/meiburg/n/n5cd098a8c744&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/yasushi-jp/items/97057509e96919c35f64" target="_blank" rel="noopener"
 &gt;https://qiita.com/yasushi-jp/items/97057509e96919c35f64&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、上記だと変数を展開することができないので、そのような場合には以下のように &lt;code&gt;ExecStartPre&lt;/code&gt; で &lt;code&gt;systemctl&lt;/code&gt; の &lt;code&gt;set-environment&lt;/code&gt; を使う方法などがあるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/kobanyan/items/f8e8a3bd5406e1d290fb" target="_blank" rel="noopener"
 &gt;https://qiita.com/kobanyan/items/f8e8a3bd5406e1d290fb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ただ、今回の私の場合は、シェル変数 &lt;code&gt;HOSTNAME&lt;/code&gt; を環境変数に export して参照したかったのですが、systemd にはホスト名を表す特殊な変数として &lt;code&gt;%H&lt;/code&gt; があるようなので、これを使って以下のようにすれば解決できました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[Unit]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Description=My Python App
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[Service]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ExecStart=/path/to/your/python/app.py
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Environment=&amp;#34;HOSTNAME=%H&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[Install]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WantedBy=multi-user.target
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://ja.stackoverflow.com/questions/62360/systemd-%E3%81%8B%E3%82%89%E3%81%AE%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E8%B5%B7%E5%8B%95%E6%99%82%E3%81%ABhome%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%9F%E3%81%84" target="_blank" rel="noopener"
 &gt;https://ja.stackoverflow.com/questions/62360/systemd-%E3%81%8B%E3%82%89%E3%81%AE%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E8%B5%B7%E5%8B%95%E6%99%82%E3%81%ABhome%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%9F%E3%81%84&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/kobanyan/items/f8e8a3bd5406e1d290fb" target="_blank" rel="noopener"
 &gt;https://qiita.com/kobanyan/items/f8e8a3bd5406e1d290fb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/37864999/referencing-other-environment-variables-in-systemd" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/37864999/referencing-other-environment-variables-in-systemd&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>VSCode で現在アクティブなタブの背景色を変更する</title><link>https://blog.ponkotools.com/posts/2023/06/12/vscode/</link><pubDate>Mon, 12 Jun 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/06/12/vscode/</guid><description>&lt;p&gt;Visual Studio Code のエディタで現在アクティブなタブの背景色が、デフォルトだと他のタブとあまり変わらなくて分かりづらいので、設定で変更しました。&lt;/p&gt;
&lt;p&gt;メニューより、ファイル &amp;gt; ユーザー設定 &amp;gt; 設定 を選択します。&lt;/p&gt;
&lt;p&gt;設定の検索より &lt;code&gt;workbench.colorCustomizations&lt;/code&gt; と入力し、「settings.json で編集」をクリックします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="485px" data-flex-grow="202" height="282" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2023/06/12/vscode/vscode.png" width="570"&gt;&lt;/p&gt;
&lt;p&gt;そして、以下のように &lt;code&gt;tab.activeBackground&lt;/code&gt; を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;workbench.colorCustomizations&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;tab.activeBackground&amp;#34;: &amp;#34;#1b77cf&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://tekunabe.hatenablog.jp/entry/2021/05/23/134458" target="_blank" rel="noopener"
 &gt;https://tekunabe.hatenablog.jp/entry/2021/05/23/134458&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Telegraf で Jetson の GPU 情報を取得する</title><link>https://blog.ponkotools.com/posts/2023/05/27/telegraf/</link><pubDate>Sat, 27 May 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/05/27/telegraf/</guid><description>&lt;p&gt;Telegraf で GPU 情報を取得しよううとしたのですが、Jetson には &lt;code&gt;nvidia-smi&lt;/code&gt; のコマンドがありません。&lt;/p&gt;
&lt;p&gt;どうしようかなと思っていたら、以下の記事に Jetson で GPU 情報を取得する方法が書いてありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.influxdata.com/blog/nvidia-jetson-series-part-1-jetson-stats/" target="_blank" rel="noopener"
 &gt;https://www.influxdata.com/blog/nvidia-jetson-series-part-1-jetson-stats/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これを参考に、InfluxDB にデータを保存し、Grafana で可視化まで行いました。&lt;br&gt;
尚、TIG Stack (Telegraf, InfluxDB, Grafana) については以下を参考にしてください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/12/telegraf-influxdb-garafana.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2021/12/telegraf-influxdb-garafana.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Jetson Xavier NX&lt;/li&gt;
&lt;li&gt;Ubuntu 18.04&lt;/li&gt;
&lt;li&gt;Telegraf 1.23.0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Telegraf, InfluxDB, Grafana は Docker で動作させています。&lt;/p&gt;
&lt;h2 id="jetson-stats-のインストール"&gt;&lt;a href="#jetson-stats-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;Jetson Stats のインストール
&lt;/h2&gt;&lt;p&gt;まずはホストに Jetson Stats をインストールします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get install python3-pip
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo -H python3 -m pip install -U jetson-stats
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;インストール後、一度ログアウト or 再起動します。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;jtop&lt;/code&gt; を実行して動作確認します。&lt;/p&gt;
&lt;h2 id="telegraf-の設定"&gt;&lt;a href="#telegraf-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Telegraf の設定
&lt;/h2&gt;&lt;p&gt;Jetson Stats を使って GPU の情報を取得する python スクリプトを作成し、それを Telegraf から定期的に実行するようにします。&lt;br&gt;
ただし、今回 Telegraf は Docker コンテナで動かしているので、上記の記事そのままでは上手く行きません。&lt;/p&gt;
&lt;h3 id="python-スクリプトの作成"&gt;&lt;a href="#python-%e3%82%b9%e3%82%af%e3%83%aa%e3%83%97%e3%83%88%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;Python スクリプトの作成
&lt;/h3&gt;&lt;p&gt;上記の記事にある以下のスクリプトを &lt;code&gt;jetson_stats.py&lt;/code&gt; という名前で保存しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Import jtop python library. We will use this to access the Jetson_Stats service.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;jtop&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;jtop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;jtop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;jetson&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# jetson.stats provides our system measurements as type dict.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jetson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stats&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# time and uptime are proved as time objects. These needed to be converted before passing as a JSON string,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;%m/&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s1"&gt;/%Y&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;uptime&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;uptime&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# We then convert our dict -&amp;amp;gt; Json string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;influx_json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;jetson&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;influx_json&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このスクリプトを Telegraf から定期的に実行することになります。&lt;/p&gt;
&lt;h3 id="dockerfile-の作成"&gt;&lt;a href="#dockerfile-%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;Dockerfile の作成
&lt;/h3&gt;&lt;p&gt;今までは Telegraf の Docker イメージをそのまま使っていましたが、このコンテナには Python の実行環境が入っていないため、上記の Python スクリプトを動かすことができません。&lt;br&gt;
そこで、以下のような Dockerfile を作成しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;telegraf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.23&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ARG&lt;/span&gt; &lt;span class="n"&gt;DEBIAN_FRONTEND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;noninteractive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;COPY&lt;/span&gt; &lt;span class="n"&gt;jetson_stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;recommends&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;python3&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;setuptools&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;wheel&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;autoremove&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rf&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lists&lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;pip3&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;jetson&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;stats&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;jetson_stats.py&lt;/code&gt; をイメージ内にコピーし、あとは Python の実行環境と Jetson Stats をインストールしています。&lt;/p&gt;
&lt;h3 id="docker-composeyml-の変更"&gt;&lt;a href="#docker-composeyml-%e3%81%ae%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;docker-compose.yml の変更
&lt;/h3&gt;&lt;p&gt;コンテナ内で Jetson Stats を使うためには、&lt;code&gt;/run/jtop.sock&lt;/code&gt; をマウントする必要があるようです。&lt;br&gt;
ただ、それだけではアクセス権限の関係で以下のようなエラーが表示されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;jtop.core.exceptions.JtopException: I can&amp;#39;t access jetson_stats.service.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Docker コンテナの実行ユーザーを &lt;code&gt;/run/jtop.sock&lt;/code&gt; の所有グループに加えたら解決できたので、&lt;code&gt;group_add&lt;/code&gt; のプロパティを追加します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/rbonghi/jetson_stats" target="_blank" rel="noopener"
 &gt;https://github.com/rbonghi/jetson_stats&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上を踏まえ、docker-compose.yml を以下のように変更しました（今回に関連する部分のみ抜粋）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;telegraf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;telegraf&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;telegraf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;HOSTNAME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;NVIDIA_VISIBLE_DEVICES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;NVIDIA_DRIVER_CAPABILITIES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reservations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;gpu&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;unless&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;stopped&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;6514&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;6514&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;telegraf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;telegraf&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;telegraf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ro&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ro&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nvidia&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;smi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nvidia&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;smi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ro&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 以下は Jetson Xavier NX 用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;jtop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;jtop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ro&lt;/span&gt; &lt;span class="c1"&gt;# https://github.com/rbonghi/jetson_stats&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;TELEGRAF_UID_GID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;group_add&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;${JTOP_GID:?}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="環境変数の追加"&gt;&lt;a href="#%e7%92%b0%e5%a2%83%e5%a4%89%e6%95%b0%e3%81%ae%e8%bf%bd%e5%8a%a0" class="header-anchor"&gt;&lt;/a&gt;環境変数の追加
&lt;/h3&gt;&lt;p&gt;上記の docker-compose.yml 内にある &lt;code&gt;JTOP_GID&lt;/code&gt; という環境変数を定義します。&lt;br&gt;
&lt;code&gt;~/.bashrc&lt;/code&gt; に以下を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;JTOP_GID&lt;/span&gt;&lt;span class="o"&gt;=$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stat&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%g&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;jtop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再読み込みします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~$ &lt;span class="nb"&gt;source&lt;/span&gt; .bashrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで、&lt;code&gt;/run/jtop.sock&lt;/code&gt; の所有グループを &lt;code&gt;JTOP_GID&lt;/code&gt; で参照できます。&lt;/p&gt;
&lt;h3 id="telegrafconf-の設定"&gt;&lt;a href="#telegrafconf-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;telegraf.conf の設定
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;telegraf.conf&lt;/code&gt; に以下を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[[inputs.exec]]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ## Commands array
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; commands = [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;python3 /usr/local/bin/jetson_stats.py&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ## Timeout for each command to complete.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; timeout = &amp;#34;5s&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ## measurement name suffix (for separating different commands)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; name_suffix = &amp;#34;_jetson_stats&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ## Data format to consume.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ## Each data format has its own unique set of configuration options, read
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ## more about them here:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; data_format = &amp;#34;json&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ## Array of glob pattern strings or booleans keys that should be added as string fields.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; json_string_fields = [&amp;#34;jetson_uptime&amp;#34;, &amp;#34;jetson_nvp model&amp;#34;, &amp;#34;jetson_NVENC&amp;#34;, &amp;#34;jetson_NVDEC&amp;#34;, &amp;#34;jetson_NVJPG&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;内容は前述の参考記事の中身そのままです。&lt;/p&gt;
&lt;h3 id="テスト"&gt;&lt;a href="#%e3%83%86%e3%82%b9%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;テスト
&lt;/h3&gt;&lt;p&gt;Docker コンテナに入って、以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python3 jetson_stats.py
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;json が取得できていれば OK です。&lt;/p&gt;
&lt;h2 id="grafana-のダッシュボードを作成"&gt;&lt;a href="#grafana-%e3%81%ae%e3%83%80%e3%83%83%e3%82%b7%e3%83%a5%e3%83%9c%e3%83%bc%e3%83%89%e3%82%92%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;Grafana のダッシュボードを作成
&lt;/h2&gt;&lt;p&gt;Jetson Stats 用のテンプレートがないかなと探してみましたが、見つかりませんでした。&lt;br&gt;
どうやら自分で作成するしかなさそうです。&lt;/p&gt;
&lt;p&gt;参考として、&lt;code&gt;jetson_stats.py&lt;/code&gt; を実行したら以下のような出力が得られます（わかりやすいように整形しています）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;jetson&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;09/14/2022&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;uptime&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0:40:39.970000&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;jetson_clocks&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;OFF&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;nvp model&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;MODE_10W_DESKTOP&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;CPU1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;CPU2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;CPU3&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;CPU4&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;CPU5&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;OFF&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;CPU6&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;OFF&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;GPU&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;MTS FG&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;MTS BG&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;RAM&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1413804&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;EMC&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1413804&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;SWAP&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;APE&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;NVENC&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;OFF&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;NVDEC&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;OFF&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;NVJPG&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;OFF&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;fan&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Temp AO&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;42.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Temp AUX&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;42.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Temp CPU&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;42.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Temp GPU&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;41.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Temp thermal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;42.15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;power cur&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4166&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;power avg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4166&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これらの値が InfluxDB に格納されているはずなので、その値を使ってダッシュボードを作成していきます。&lt;br&gt;
尚、各プロパティの説明は以下にありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://rnext.it/jetson_stats/jtop.html#jtop.jtop.jtop.stats" target="_blank" rel="noopener"
 &gt;https://rnext.it/jetson_stats/jtop.html#jtop.jtop.jtop.stats&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;単位くらい書いておいてほしいなぁ〜。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.influxdata.com/blog/nvidia-jetson-series-part-1-jetson-stats/" target="_blank" rel="noopener"
 &gt;https://www.influxdata.com/blog/nvidia-jetson-series-part-1-jetson-stats/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/rbonghi/jetson_stats" target="_blank" rel="noopener"
 &gt;https://github.com/rbonghi/jetson_stats&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/rbonghi/jetson_stats/issues/63" target="_blank" rel="noopener"
 &gt;https://github.com/rbonghi/jetson_stats/issues/63&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/manabuishiirb/items/a2620ec8020811540d81" target="_blank" rel="noopener"
 &gt;https://qiita.com/manabuishiirb/items/a2620ec8020811540d81&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/grafana/dashboards/14493-nvidia-jetson/" target="_blank" rel="noopener"
 &gt;https://grafana.com/grafana/dashboards/14493-nvidia-jetson/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>MongoDB と 2106 年問題</title><link>https://blog.ponkotools.com/posts/2023/05/23/mongodb/</link><pubDate>Tue, 23 May 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/05/23/mongodb/</guid><description>&lt;p&gt;ボタン電池がなくなり、RTC が遥か未来になったときに MongoDB が動作しなくなりました。（正確には、Python アプリにおいて、MongoDB の初期化を行う際にエラーとなりました。）&lt;/p&gt;
&lt;p&gt;MongoDB のバージョンは 6.0.5 です。&lt;/p&gt;
&lt;p&gt;調べてみると、MongoDB の ObjectID は先頭の4バイトがタイムスタンプ(UNIX タイム)となっているそうです。&lt;br&gt;
MongoDB はこれを符号なし整数として扱っていて、その場合の上限は &lt;code&gt;4,294,967,295&lt;/code&gt; であり、これは UTC で2106年2月7日6時28分16秒となります。&lt;br&gt;
というわけで、MongoDB はいわゆる 2106 年問題を孕んでいることになります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.wdic.org/w/TECH/2106%E5%B9%B4%E5%95%8F%E9%A1%8C" target="_blank" rel="noopener"
 &gt;https://www.wdic.org/w/TECH/2106%E5%B9%B4%E5%95%8F%E9%A1%8C&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ちなみに、4バイトがタイムスタンプを符号付き整数として扱っている場合は 2038 年問題となります。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/42097779/how-can-mongodb-handle-objectid-timestamp-beyond-tue-19-jan-2038" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/42097779/how-can-mongodb-handle-objectid-timestamp-beyond-tue-19-jan-2038&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://jira.mongodb.org/browse/GODRIVER-1092" target="_blank" rel="noopener"
 &gt;https://jira.mongodb.org/browse/GODRIVER-1092&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.wdic.org/w/TECH/2106%E5%B9%B4%E5%95%8F%E9%A1%8C" target="_blank" rel="noopener"
 &gt;https://www.wdic.org/w/TECH/2106%E5%B9%B4%E5%95%8F%E9%A1%8C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.mongodb.com/blog/post/generating-globally-unique-identifiers-for-use-with-mongodb" target="_blank" rel="noopener"
 &gt;https://www.mongodb.com/blog/post/generating-globally-unique-identifiers-for-use-with-mongodb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] docker-compose の env_file 内でシェルスクリプトを実行する</title><link>https://blog.ponkotools.com/posts/2023/05/12/docker/</link><pubDate>Fri, 12 May 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/05/12/docker/</guid><description>&lt;p&gt;Docker Compose の env_file ディレクティブを使用する場合、原則として env_file に指定されたファイル内でシェルのシンタックスを使用することはできません。&lt;/p&gt;
&lt;p&gt;しかし、env_file にはシェルスクリプトを指定することもできますので、以下のようにシェルスクリプトファイル（例えば、env.shとします）を作成することで対応できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;MY_VARIABLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my_value
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;docker-compose.yml の env_file ディレクティブでシェルスクリプトファイルを指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;3&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;myservice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./env.sh&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意点として、シェルスクリプトのパーミッションを正しく設定する必要があります。&lt;br&gt;
また、シェルスクリプト内で環境変数を定義する場合には &lt;code&gt;export&lt;/code&gt; する必要があります。&lt;/p&gt;
&lt;p&gt;ちなみに、env_file で定義された環境変数は、コンテナ内では使えますが、docker-compose.yml 内では使えません。&lt;br&gt;
（これでちょっとはまりました。）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://zenn.dev/rhene/scraps/781fdbecd340d3" target="_blank" rel="noopener"
 &gt;https://zenn.dev/rhene/scraps/781fdbecd340d3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://maku77.github.io/p/8r3cmu5/" target="_blank" rel="noopener"
 &gt;https://maku77.github.io/p/8r3cmu5/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://zenn.dev/rhene/scraps/781fdbecd340d3" target="_blank" rel="noopener"
 &gt;https://zenn.dev/rhene/scraps/781fdbecd340d3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] SyslogHandler でログを送信したときに `Bad file descriptor` のエラーになる</title><link>https://blog.ponkotools.com/posts/2023/04/05/python/</link><pubDate>Wed, 05 Apr 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/04/05/python/</guid><description>&lt;p&gt;SyslogHandler を使ってログを記録していたのですが、&lt;code&gt;Bad file descriptor&lt;/code&gt; のエラーが表示されてはまってしまいました。&lt;/p&gt;
&lt;p&gt;表示されたエラーは以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/usr/lib/python3.8/logging/handlers.py&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;940&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;emit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sendto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ne"&gt;OSError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Errno&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;Bad&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="n"&gt;descriptor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;アプリをマルチプロセスで動かしており、FastAPI ( +uvicorn) を使うとこのエラーが出るようになりました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Python 3.8.10&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="対処方法"&gt;&lt;a href="#%e5%af%be%e5%87%a6%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;対処方法
&lt;/h2&gt;&lt;p&gt;調べても原因がさっぱりわからなかったのですが、最終的に以下のページにたどり着きました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/python/cpython/issues/87362" target="_blank" rel="noopener"
 &gt;https://github.com/python/cpython/issues/87362&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;どうやら Python の logging モジュールの不具合のようで、Python のバージョンを 3.11 まで上げると直りました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/python/cpython/issues/87362" target="_blank" rel="noopener"
 &gt;https://github.com/python/cpython/issues/87362&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] マルチプロセスにおけるロギング (QueueHandler, QueueListener)</title><link>https://blog.ponkotools.com/posts/2023/04/04/python/</link><pubDate>Tue, 04 Apr 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/04/04/python/</guid><description>&lt;p&gt;SyslogHandler で UDP でログを記録していたのですが、マルチプロセスでは Socket 通信のところでエラーが発生しました。&lt;br&gt;
マルチプロセスでのロギングでは、&lt;code&gt;QueueHandler&lt;/code&gt; と &lt;code&gt;QueueListner&lt;/code&gt; を使ってログを一箇所に集約して書き込むようにする必要があります。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Python 3.8.10&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="基本的な書き方"&gt;&lt;a href="#%e5%9f%ba%e6%9c%ac%e7%9a%84%e3%81%aa%e6%9b%b8%e3%81%8d%e6%96%b9" class="header-anchor"&gt;&lt;/a&gt;基本的な書き方
&lt;/h2&gt;&lt;p&gt;とりあえずマルチプロセスは置いておいて、&lt;code&gt;QueueHandler&lt;/code&gt; と &lt;code&gt;QueueListener&lt;/code&gt; の基本的な使い方です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StreamHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DEBUG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 標準出力の設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;stream_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StreamHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;stream_handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%(asctime)s&lt;/span&gt;&lt;span class="s1"&gt; [&lt;/span&gt;&lt;span class="si"&gt;%(levelname)s&lt;/span&gt;&lt;span class="s1"&gt;] [&lt;/span&gt;&lt;span class="si"&gt;%(name)s&lt;/span&gt;&lt;span class="s1"&gt;] &lt;/span&gt;&lt;span class="si"&gt;%(message)s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Syslog 出力の設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;syslog_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SysLogHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;514&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;syslog_handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;HOSTNAME&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; ris-main: %(message)s&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ファイル出力の設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;file_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimedRotatingFileHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;log/sample.log&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;file_handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%(asctime)s&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="si"&gt;%(msecs)03d&lt;/span&gt;&lt;span class="s1"&gt; [&lt;/span&gt;&lt;span class="si"&gt;%(levelname)s&lt;/span&gt;&lt;span class="s1"&gt;] [&lt;/span&gt;&lt;span class="si"&gt;%(name)s&lt;/span&gt;&lt;span class="s1"&gt;] &lt;/span&gt;&lt;span class="si"&gt;%(message)s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datefmt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;%Y-%m-&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s1"&gt; %H:%M:%S&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# キューハンドラの設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;queue_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueueHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;que&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;queue_handler&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リスナーの作成と開始&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;queue_listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueueListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;que&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stream_handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;syslog_handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_handler&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;queue_listener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is info&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is debug&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;critical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is critical&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;queue_listener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;logger&lt;/code&gt; を使って書いたログは &lt;code&gt;QueueHandler&lt;/code&gt; によりキューに入れられます。&lt;br&gt;
&lt;code&gt;QueueListner&lt;/code&gt; はキューに溜まったログを取り出して、&lt;code&gt;StreamHandler&lt;/code&gt; &lt;code&gt;SyslogHandler&lt;/code&gt; &lt;code&gt;TimedRotatingFileHandler&lt;/code&gt; で記録されます。&lt;/p&gt;
&lt;p&gt;尚、上記は &lt;code&gt;basicConfig&lt;/code&gt; を使って設定していますので、ライブラリなどのロギングにも影響します（対処方法は後述）。&lt;/p&gt;
&lt;h3 id="マルチプロセスで試してみた"&gt;&lt;a href="#%e3%83%9e%e3%83%ab%e3%83%81%e3%83%97%e3%83%ad%e3%82%bb%e3%82%b9%e3%81%a7%e8%a9%a6%e3%81%97%e3%81%a6%e3%81%bf%e3%81%9f" class="header-anchor"&gt;&lt;/a&gt;マルチプロセスで試してみた
&lt;/h3&gt;&lt;p&gt;上記を踏まえ、プロセスを３つ立ち上げ、各プロセス100回ログを記録させてみたサンプルが以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StreamHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DEBUG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;(&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;) this is info&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;(&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;) this is debug&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;critical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;(&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;) this is critical&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 標準出力の設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;stream_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StreamHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;stream_handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%(asctime)s&lt;/span&gt;&lt;span class="s1"&gt; [&lt;/span&gt;&lt;span class="si"&gt;%(levelname)s&lt;/span&gt;&lt;span class="s1"&gt;] [&lt;/span&gt;&lt;span class="si"&gt;%(name)s&lt;/span&gt;&lt;span class="s1"&gt;] &lt;/span&gt;&lt;span class="si"&gt;%(message)s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Syslog 出力の設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;syslog_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SysLogHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;514&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;syslog_handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;HOSTNAME&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; ris-main: %(message)s&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ファイル出力の設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;file_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimedRotatingFileHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;log/sample.log&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;file_handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%(asctime)s&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="si"&gt;%(msecs)03d&lt;/span&gt;&lt;span class="s1"&gt; [&lt;/span&gt;&lt;span class="si"&gt;%(levelname)s&lt;/span&gt;&lt;span class="s1"&gt;] [&lt;/span&gt;&lt;span class="si"&gt;%(name)s&lt;/span&gt;&lt;span class="s1"&gt;] &lt;/span&gt;&lt;span class="si"&gt;%(message)s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datefmt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;%Y-%m-&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s1"&gt; %H:%M:%S&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# キューハンドラの設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;queue_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueueHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;que&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;queue_handler&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リスナーの作成と開始&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;queue_listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueueListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;que&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stream_handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;syslog_handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_handler&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;queue_listener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# プロセスの立ち上げ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;processes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;processes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# プロセスの終了を待つ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;processes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;queue_listener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;問題なくログが記録できていることが確認できました。&lt;/p&gt;
&lt;h2 id="basicconfig-を使わずに設定する"&gt;&lt;a href="#basicconfig-%e3%82%92%e4%bd%bf%e3%82%8f%e3%81%9a%e3%81%ab%e8%a8%ad%e5%ae%9a%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;basicConfig を使わずに設定する
&lt;/h2&gt;&lt;p&gt;上述したように、&lt;code&gt;basicConfig&lt;/code&gt; を使うとライブラリなどの全てのモジュールに影響するので、&lt;code&gt;logger&lt;/code&gt; に対して設定を行うようにします。&lt;br&gt;
ただ、そうなると都度設定を行う必要が出てくるので、以下のページを参考に共通の関数を作成しました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://joemphilips.com/post/python_logging/" target="_blank" rel="noopener"
 &gt;http://joemphilips.com/post/python_logging/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ただし、QueueHandler を使う場合、キューを渡してやる必要があるので、それはグローバル変数として用意することにしました。&lt;br&gt;
ここらへん、もっと良い実装方法はないかなぁとは思いますが・・・。&lt;/p&gt;
&lt;p&gt;以下、サンプルです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# mylogger.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging.handlers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;log_queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34; 共通のロガーを作成するための関数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; logging.getLogger と簡単に差し替えられるように同じ関数名としておく
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# キューハンドラの設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;queue_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueueHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_queue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue_handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# main.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StreamHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;INFO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mylogger&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;log_queue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 標準出力の設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;stream_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StreamHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;stream_handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%(asctime)s&lt;/span&gt;&lt;span class="s1"&gt; [&lt;/span&gt;&lt;span class="si"&gt;%(levelname)s&lt;/span&gt;&lt;span class="s1"&gt;] [&lt;/span&gt;&lt;span class="si"&gt;%(name)s&lt;/span&gt;&lt;span class="s1"&gt;] &lt;/span&gt;&lt;span class="si"&gt;%(message)s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;stream_handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Syslog 出力の設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;syslog_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SysLogHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;514&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;syslog_handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;HOSTNAME&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; ris-main: %(message)s&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;syslog_handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ファイル出力の設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;file_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimedRotatingFileHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;log/sample.log&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;file_handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%(asctime)s&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="si"&gt;%(msecs)03d&lt;/span&gt;&lt;span class="s1"&gt; [&lt;/span&gt;&lt;span class="si"&gt;%(levelname)s&lt;/span&gt;&lt;span class="s1"&gt;] [&lt;/span&gt;&lt;span class="si"&gt;%(name)s&lt;/span&gt;&lt;span class="s1"&gt;] &lt;/span&gt;&lt;span class="si"&gt;%(message)s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datefmt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;%Y-%m-&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s1"&gt; %H:%M:%S&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;file_handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# リスナーの作成と開始&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;queue_listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueueListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;log_queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stream_handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;syslog_handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_handler&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;respect_handler_level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;queue_listener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is info&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is debug&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;critical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is critical&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;queue_listener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、ここでは標準出力とそれ以外で、出力するログレベルを変えています。&lt;br&gt;
この場合、&lt;code&gt;QueueHandler&lt;/code&gt; の &lt;code&gt;respect_handler_level&lt;/code&gt; を &lt;code&gt;True&lt;/code&gt; にして、各ハンドラー側のレベルを優先するように設定してやる必要があります。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.python.org/ja/3.8/library/logging.handlers.html" target="_blank" rel="noopener"
 &gt;https://docs.python.org/ja/3.8/library/logging.handlers.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://ikatakos.com/pot/programming/python/packages/multiprocessing/queuehandler" target="_blank" rel="noopener"
 &gt;https://ikatakos.com/pot/programming/python/packages/multiprocessing/queuehandler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://rob-blackbourn.medium.com/how-to-use-python-logging-queuehandler-with-dictconfig-1e8b1284e27a" target="_blank" rel="noopener"
 &gt;https://rob-blackbourn.medium.com/how-to-use-python-logging-queuehandler-with-dictconfig-1e8b1284e27a&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://joemphilips.com/post/python_logging/" target="_blank" rel="noopener"
 &gt;http://joemphilips.com/post/python_logging/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide] QTimer の使い方</title><link>https://blog.ponkotools.com/posts/2023/03/28/qtimer/</link><pubDate>Tue, 28 Mar 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/03/28/qtimer/</guid><description>&lt;p&gt;スレッドを使わずに定期的に GUI を更新するために、&lt;code&gt;QTimer&lt;/code&gt; の使い方と挙動について簡単に調べてみました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Python 3.8.10&lt;/li&gt;
&lt;li&gt;PySide 6.2.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtCore&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QTimer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtWidgets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QLabel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;メインウィンドウ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;countup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__current_count&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;singleShot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__single_shot1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;singleShot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__single_shot2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__label&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__current_count&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#time.sleep(3)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__current_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;現在のカウント: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__single_shot1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, 10秒経過&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__single_shot2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, 15秒経過&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;main_window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;main_window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;　&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:40.166652, 1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:41.115886, 2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:42.066937, 3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:43.026873, 4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:44.026648, 5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:45.026877, 6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:46.026574, 7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:47.026898, 8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:48.026477, 9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:49.027008, 10秒経過
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:49.027169, 10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:50.027045, 11
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:51.026868, 12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:52.027034, 13
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:53.026916, 14
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:54.026824, 15秒経過
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:04:54.027010, 15
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="処理に時間がかかった場合はどうなる"&gt;&lt;a href="#%e5%87%a6%e7%90%86%e3%81%ab%e6%99%82%e9%96%93%e3%81%8c%e3%81%8b%e3%81%8b%e3%81%a3%e3%81%9f%e5%a0%b4%e5%90%88%e3%81%af%e3%81%a9%e3%81%86%e3%81%aa%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;処理に時間がかかった場合はどうなる？
&lt;/h3&gt;&lt;p&gt;上記のコードでは、1秒ごとに &lt;code&gt;__timeout&lt;/code&gt; 関数が実行されますが、もしその中で処理に時間がかかったとしたらどうなるか？&lt;br&gt;
試しに3秒のスリープを入れてみました（上記のコメントアウトを解除）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:07:10.458991, 1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:07:13.462465, 2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:07:16.464238, 3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:07:19.467192, 4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:07:22.470589, 10秒経過
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:07:22.471410, 5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:07:25.475184, 6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:07:28.478740, 15秒経過
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:07:28.480526, 7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2023-03-27 14:07:31.484492, 8
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;3秒経過後、すぐに &lt;code&gt;__timeout&lt;/code&gt; がコールされています。&lt;br&gt;
前の処理が完了しないと次の処理は行われないようです。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://fereria.github.io/reincarnation_tech/11_PySide/01_PySide_Basic/00_Tutorial/13_timer/" target="_blank" rel="noopener"
 &gt;https://fereria.github.io/reincarnation_tech/11_PySide/01_PySide_Basic/00_Tutorial/13_timer/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://fereria.github.io/reincarnation_tech/11_PySide/00_Tutorial/13_timer/" target="_blank" rel="noopener"
 &gt;https://fereria.github.io/reincarnation_tech/11_PySide/00_Tutorial/13_timer/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Nginx の proxy_pass で名前解決されない</title><link>https://blog.ponkotools.com/posts/2023/03/14/nginx/</link><pubDate>Tue, 14 Mar 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/03/14/nginx/</guid><description>&lt;p&gt;nginx を Docker コンテナとして動かしており、ホスト側へリバースプロキシを行おうとした際にはまってしまいました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;docker 20.10.21&lt;/li&gt;
&lt;li&gt;nginx 1.23.3&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="問題と対策"&gt;&lt;a href="#%e5%95%8f%e9%a1%8c%e3%81%a8%e5%af%be%e7%ad%96" class="header-anchor"&gt;&lt;/a&gt;問題と対策
&lt;/h2&gt;&lt;p&gt;Docker コンテナ内からホストにアクセスする際には &lt;code&gt;host.docker.internal&lt;/code&gt; を指定します。&lt;br&gt;
これについては以下の記事を参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/06/docker.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/06/docker.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;その上で、nginx の設定で以下のようにリバースプロキシの設定を行いました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="n"&gt;default_server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;server_name&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;hoge&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;resolver&lt;/span&gt; &lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.11&lt;/span&gt; &lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;dummy_var&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;internal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rewrite&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;hoge&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="o"&gt;/$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_pass&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;dummy_var&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;Upgrade&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;Connection&lt;/span&gt; &lt;span class="n"&gt;keep&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;alive&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_cache_bypass&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Proto&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;すると、以下のように名前解決できないというエラーが表示されました。&lt;/p&gt;
&lt;p&gt;尚、コンテナ内に入って &lt;code&gt;curl&lt;/code&gt; などを使ってテストすると、きちんと &lt;code&gt;host.docker.internal&lt;/code&gt; の名前解決がされていました。&lt;br&gt;
いろいろ調べてみると、どうやら &lt;code&gt;proxy_pass&lt;/code&gt; では &lt;code&gt;/etc/hosts&lt;/code&gt; が参照されないそうです。&lt;/p&gt;
&lt;p&gt;どのように対応しようか悩んでいたところ、&lt;code&gt;upstream&lt;/code&gt; の設定ではきちんと &lt;code&gt;/etc/hosts&lt;/code&gt; が参照されるようでしたので、以下のように設定して回避することにしました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;upstream&lt;/span&gt; &lt;span class="n"&gt;backends&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;internal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="n"&gt;default_server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;server_name&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;hoge&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;resolver&lt;/span&gt; &lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.11&lt;/span&gt; &lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;dummy_var&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;backends&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rewrite&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;hoge&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="o"&gt;/$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_pass&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;dummy_var&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;Upgrade&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;Connection&lt;/span&gt; &lt;span class="n"&gt;keep&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;alive&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_cache_bypass&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_set_header&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Proto&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/yKanazawa/items/2136c4880e8d48370981" target="_blank" rel="noopener"
 &gt;https://qiita.com/yKanazawa/items/2136c4880e8d48370981&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://rougeref.hatenablog.com/entry/2022/06/13/185501" target="_blank" rel="noopener"
 &gt;https://rougeref.hatenablog.com/entry/2022/06/13/185501&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/tksugimoto/items/804e0051bf1b1ddab168" target="_blank" rel="noopener"
 &gt;https://qiita.com/tksugimoto/items/804e0051bf1b1ddab168&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Nginx で upstream の 名前解決を無効化（回避）する方法</title><link>https://blog.ponkotools.com/posts/2023/02/16/nginx/</link><pubDate>Thu, 16 Feb 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/02/16/nginx/</guid><description>&lt;p&gt;Docker で動かしている Nginx でリバースプロキシの設定を行い、別の Docker コンテナに転送するように設定したときにちょっとはまったのでメモです。&lt;/p&gt;
&lt;p&gt;コンテナ同士はコンテナ名を使ってアクセスできるので、Nginx の設定では以下のようにリバースプロキシの設定を行っています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;location /some_path {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_pass http://container-name.docker-network:port;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このとき、Nginx は 起動時に upstream の名前解決を行っているので、上記の URL の名前解決ができない場合（つまり転送先のコンテナが起動していない）と &lt;code&gt;host not found in upstream&lt;/code&gt; というエラーが表示されて起動に失敗します。&lt;/p&gt;
&lt;p&gt;私の場合、仕様によって起動するコンテナの数が異なったり、開発中は一部のコンテナだけ起動して確認したりするので、その都度 Nginx の設定を変えるのは面倒です。&lt;br&gt;
なので、名前解決できなくても Nginx が起動できるように回避策がないかと調べた所、以下の記事に書いてありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://serverfault.com/questions/700894/make-nginx-ignore-site-config-when-its-upstream-cannot-be-reached" target="_blank" rel="noopener"
 &gt;https://serverfault.com/questions/700894/make-nginx-ignore-site-config-when-its-upstream-cannot-be-reached&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;resolver&lt;/code&gt; のディレクティブを使って名前解決してやることで回避できるそうです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;some_path&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;resolver&lt;/span&gt; &lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# resolver 8.8.8.8 valid=30s; # or some other DNS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# resolver 127.0.0.11 valid=30s; # or Docker&amp;#39;s DNS server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;dummy_var&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;proxy_pass&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;dummy_var&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;私の場合、Nginx を Docker で動かしているので、&lt;code&gt;127.0.0.11&lt;/code&gt; をリゾルバに指定することで、転送先のコンテナが起動していなくても Nginx が起動できるようになりました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://architecting.hateblo.jp/entry/2021/01/12/124135" target="_blank" rel="noopener"
 &gt;https://architecting.hateblo.jp/entry/2021/01/12/124135&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://serverfault.com/questions/700894/make-nginx-ignore-site-config-when-its-upstream-cannot-be-reached" target="_blank" rel="noopener"
 &gt;https://serverfault.com/questions/700894/make-nginx-ignore-site-config-when-its-upstream-cannot-be-reached&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Linux で端末にリアルタイムに日時を表示する</title><link>https://blog.ponkotools.com/posts/2023/02/02/linux/</link><pubDate>Thu, 02 Feb 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/02/02/linux/</guid><description>&lt;p&gt;&lt;code&gt;watch&lt;/code&gt; コマンドと &lt;code&gt;date&lt;/code&gt; コマンドを組み合わせると簡単にできます。&lt;/p&gt;
&lt;p&gt;例えば以下のような感じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ watch -t -n 0.01 date +%T.%N
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;watch&lt;/code&gt; は引数で指定したコマンドを一定間隔ごとに繰り返し実行するコマンドです。&lt;br&gt;
&lt;code&gt;-t&lt;/code&gt; はヘッダを非表示にします。&lt;br&gt;
&lt;code&gt;-n&lt;/code&gt; はコマンドを実行する間隔（秒）です。&lt;br&gt;
ここでは &lt;code&gt;date&lt;/code&gt; コマンドを 0.01 秒ごとに実行しています。&lt;br&gt;
&lt;code&gt;+%T.%N&lt;/code&gt; は日時の書式です。&lt;br&gt;
例えば、以下のようにすれば日付も表示されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ watch -t -n 0.01 &amp;#34;date &amp;#39;+%Y/%m/%d %T.%N&amp;#39;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;書式にスペースを含む場合、シングルコーテーションやダブルコーテーションで括る必要があります。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/ikesato/items/4e1d2ff5251f6805b2a0" target="_blank" rel="noopener"
 &gt;https://qiita.com/ikesato/items/4e1d2ff5251f6805b2a0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hydrocul.github.io/wiki/commands/date.html" target="_blank" rel="noopener"
 &gt;https://hydrocul.github.io/wiki/commands/date.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] asyncio.Queue の動きを確認してみた</title><link>https://blog.ponkotools.com/posts/2023/02/01/python-asyncio/</link><pubDate>Wed, 01 Feb 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/02/01/python-asyncio/</guid><description>&lt;p&gt;&lt;code&gt;put&lt;/code&gt; や &lt;code&gt;get&lt;/code&gt; がコルーチンになっていたので、どういう動きになるのか確認してみました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Python 3.8.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;(&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;) before put&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;(&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;) after put&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 5回送ったらスリープ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;(&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;) get&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;出力は以下のようになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(0) before put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(0) after put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(1) before put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(1) after put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(2) before put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(2) after put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(3) before put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(3) after put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(4) before put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(4) after put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(0) get
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(1) get
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(2) get
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(3) get
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(4) get
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(5) before put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(5) after put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(6) before put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(6) after put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(7) before put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(7) after put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(8) before put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(8) after put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(9) before put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(9) after put
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(5) get
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(6) get
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(7) get
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(8) get
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(9) get
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;put&lt;/code&gt; したあと、&lt;code&gt;sleep&lt;/code&gt; したところで制御が他に移っています。&lt;br&gt;
&lt;code&gt;get&lt;/code&gt; のほうは、キューの中身を全部取り終わって次のデータ待ちになったところで制御が他に移っています。&lt;/p&gt;</description></item><item><title>[Python] 同期処理を非同期化して扱う</title><link>https://blog.ponkotools.com/posts/2023/01/26/python/</link><pubDate>Thu, 26 Jan 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/01/26/python/</guid><description>&lt;p&gt;async のついていない関数を非同期化して、async のついた非同期関数と同じように扱いたいというときの方法です。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;python 3.8.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="概要"&gt;&lt;a href="#%e6%a6%82%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;概要
&lt;/h2&gt;&lt;p&gt;同期関数を非同期化するには &lt;code&gt;run_in_executor&lt;/code&gt; を使用します。&lt;/p&gt;
&lt;p&gt;ただし、CPU バウンドな処理を非同期化しても並列では実行されないので、マルチプロセス化などを行う必要があります。
これについては以下の記事が参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://pod.hatenablog.com/entry/2019/03/21/162511" target="_blank" rel="noopener"
 &gt;https://pod.hatenablog.com/entry/2019/03/21/162511&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、&lt;code&gt;run_in_executor&lt;/code&gt; で実行する関数に名前付き引数を渡す場合、&lt;code&gt;functools.partial&lt;/code&gt; を使う必要があります。&lt;/p&gt;
&lt;p&gt;引数で渡せる値は、Python の仕様上 Picklable な値のみだそうです。&lt;br&gt;
ラムダ式やモジュールトップレベル以外で定義された関数やクラスは渡せません&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.python.org/ja/3/library/pickle.html#what-can-be-pickled-and-unpickled" target="_blank" rel="noopener"
 &gt;https://docs.python.org/ja/3/library/pickle.html#what-can-be-pickled-and-unpickled&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;p&gt;上記を踏まえたサンプルコードです。&lt;br&gt;
同期処理として CPU バウンドを想定した処理を２つ、非同期処理として I/O バウンドを想定した処理を２つ、計４つの処理を並列で動かしています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;functools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;concurrent.futures&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ProcessPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ThreadPoolExecutor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cpu_bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# CPU バウンドな処理を想定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cpu_bound[&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;] count=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;io_bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# I/O バウンドな処理を想定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;io_bound[&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;] count=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_running_loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ProcessPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_in_executor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cpu_bound&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_in_executor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cpu_bound&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;io_bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;io_bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;ProcessPoolExecutor&lt;/code&gt; により、CPU バウンドな処理はそれぞれ個別のプロセスとして動作させています。&lt;br&gt;
I/O バウンドな処理はどちらもメインプロセスで動作します。&lt;br&gt;
従って、I/O バウンドな処理のほうが少し終わるのが遅くなります。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://cpoint-lab.co.jp/article/202208/23186/" target="_blank" rel="noopener"
 &gt;https://cpoint-lab.co.jp/article/202208/23186/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://pod.hatenablog.com/entry/2019/03/21/162511" target="_blank" rel="noopener"
 &gt;https://pod.hatenablog.com/entry/2019/03/21/162511&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hachibeedi.github.io/entry/unify-sync-and-async-function-in-python/" target="_blank" rel="noopener"
 &gt;https://hachibeedi.github.io/entry/unify-sync-and-async-function-in-python/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/smatsumt/items/d8f290e40077a14210f2" target="_blank" rel="noopener"
 &gt;https://qiita.com/smatsumt/items/d8f290e40077a14210f2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.python.org/ja/3/library/pickle.html#what-can-be-pickled-and-unpickled" target="_blank" rel="noopener"
 &gt;https://docs.python.org/ja/3/library/pickle.html#what-can-be-pickled-and-unpickled&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Grafana Cloud で InfluxDB v2 のデータを可視化する</title><link>https://blog.ponkotools.com/posts/2023/01/06/influxdb-cloud/</link><pubDate>Fri, 06 Jan 2023 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2023/01/06/influxdb-cloud/</guid><description>&lt;p&gt;InfluxDB v2 ではそれ自体でダッシュボードの作成もできますが、まだまだ使いにくかったり細かい設定ができなかったりしたので、使い慣れている Grafana を使うことにしました。&lt;br&gt;
また、この機会に Grafana もオンプレミス版からクラウドサービスの Grafana Cloud に変更しました。&lt;/p&gt;
&lt;p&gt;Grafana Cloud へのサインアップ方法などは割愛します。&lt;/p&gt;
&lt;h2 id="データソースの設定"&gt;&lt;a href="#%e3%83%87%e3%83%bc%e3%82%bf%e3%82%bd%e3%83%bc%e3%82%b9%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;データソースの設定
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;サイドメニューから &lt;code&gt;Data Sources&lt;/code&gt; を選択します。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Add data source&lt;/code&gt; をクリックし、&lt;code&gt;InfluxDB&lt;/code&gt; をクリックします。&lt;/li&gt;
&lt;li&gt;InfluxDB の情報を入力します。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;InfluxDB Cloud の場合、&lt;code&gt;Query Language&lt;/code&gt; は &lt;code&gt;Flux&lt;/code&gt; を選択します。&lt;br&gt;
また、URL, トークン、バケット名が必要になるので、以下を参考に取得しておきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/12/influxdb-cloud.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/12/influxdb-cloud.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ダッシュボードパネルの作成"&gt;&lt;a href="#%e3%83%80%e3%83%83%e3%82%b7%e3%83%a5%e3%83%9c%e3%83%bc%e3%83%89%e3%83%91%e3%83%8d%e3%83%ab%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;ダッシュボード（パネル）の作成
&lt;/h2&gt;&lt;p&gt;InfluxDB v1 では GUI でポチポチと設定していくだけでグラフが表示できましたが、InfluxDB v2 では Flux で処理を書いていく必要があります。&lt;br&gt;
最初は難しかったですが、慣れればこちらのほうが簡単に思えてきました。&lt;br&gt;
いくつか例を挙げます。&lt;/p&gt;
&lt;h3 id="基本"&gt;&lt;a href="#%e5%9f%ba%e6%9c%ac" class="header-anchor"&gt;&lt;/a&gt;基本
&lt;/h3&gt;&lt;p&gt;以下にサンプルがあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/docs/grafana/latest/datasources/influxdb/query-editor/#use-macros" target="_blank" rel="noopener"
 &gt;https://grafana.com/docs/grafana/latest/datasources/influxdb/query-editor/#use-macros&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from(bucket:&amp;#34;バケット名&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; range(start: v.timeRangeStart, stop: v.timeRangeStop)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; filter(fn:(r) =&amp;gt; r._measurement == &amp;#34;メジャーメント名&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; filter(fn:(r) =&amp;gt; r[&amp;#34;_field&amp;#34;] == &amp;#34;表示したいフィールドの名前&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; aggregateWindow(every: v.windowPeriod, fn: mean)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;基本的にはこれでグラフが作成できます。&lt;/p&gt;
&lt;h3 id="一日ごとのデータを表示"&gt;&lt;a href="#%e4%b8%80%e6%97%a5%e3%81%94%e3%81%a8%e3%81%ae%e3%83%87%e3%83%bc%e3%82%bf%e3%82%92%e8%a1%a8%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;一日ごとのデータを表示
&lt;/h3&gt;&lt;p&gt;例えば株価の終値を表示したい場合などは以下のようにすることでできました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;import &amp;#34;timezone&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;option location = timezone.location(name: &amp;#34;Asia/Tokyo&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from(bucket:&amp;#34;バケット名&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; range(start: -30d, stop: now())
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; filter(fn:(r) =&amp;gt; r._measurement == &amp;#34;メジャーメント名&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; filter(fn:(r) =&amp;gt; r[&amp;#34;_field&amp;#34;] == &amp;#34;表示したいフィールドの名前&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; aggregateWindow(every: 1d, fn: last)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ポイントは &lt;code&gt;aggregateWindow(every: 1d, fn: last)&lt;/code&gt; で、一日ごとの最後の値を取得しています。&lt;/p&gt;
&lt;p&gt;また、タイムゾーンを指定しないと UTC での終値（つまり、日本時間の9時の時点の値）が取得されてしまったので、JST を指定しました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.influxdata.com/blog/time-zones-in-flux/" target="_blank" rel="noopener"
 &gt;https://www.influxdata.com/blog/time-zones-in-flux/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;尚、私の場合はグラフではなくテーブル表示にしたかったため、グラフの表示期間に関わらず &lt;code&gt;range(start: -30d, stop: now())&lt;/code&gt; で直近30日固定表示にしています。&lt;/p&gt;
&lt;h3 id="累積グラフの作成"&gt;&lt;a href="#%e7%b4%af%e7%a9%8d%e3%82%b0%e3%83%a9%e3%83%95%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;累積グラフの作成
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;cumulativeSum&lt;/code&gt; を使います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.influxdata.com/influxdb/cloud/query-data/flux/cumulativesum/" target="_blank" rel="noopener"
 &gt;https://docs.influxdata.com/influxdb/cloud/query-data/flux/cumulativesum/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例えば、日次損益の集計を行う場合などは以下のようにするとできました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;import &amp;#34;timezone&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;option location = timezone.location(name: &amp;#34;Asia/Tokyo&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from(bucket:&amp;#34;バケット名&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; range(start: -30d, stop: now())
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; filter(fn:(r) =&amp;gt; r._measurement == &amp;#34;メジャーメント名&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; filter(fn:(r) =&amp;gt; r[&amp;#34;_field&amp;#34;] == &amp;#34;表示したいフィールドの名前&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; aggregateWindow(every: 1d, fn: last)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; cumulativeSum()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一日ごとの値は取り出す方法は前述の例と同じです。&lt;br&gt;
あとはそれを &lt;code&gt;cumulativeSum()&lt;/code&gt; で加算していくだけです。&lt;br&gt;
これにより、一日ごとの値を加算してグラフに表示できます。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/aikige/items/22dc9ebc64e32a5bdfae" target="_blank" rel="noopener"
 &gt;https://qiita.com/aikige/items/22dc9ebc64e32a5bdfae&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/ekzemplaro/items/f462dfc0d81329b39c09" target="_blank" rel="noopener"
 &gt;https://qiita.com/ekzemplaro/items/f462dfc0d81329b39c09&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://rabbit-note.com/2022/09/12/influxdb-2-flux/" target="_blank" rel="noopener"
 &gt;https://rabbit-note.com/2022/09/12/influxdb-2-flux/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Influxdb Cloud を使ってみた</title><link>https://blog.ponkotools.com/posts/2022/12/26/influxdb-cloud/</link><pubDate>Mon, 26 Dec 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/12/26/influxdb-cloud/</guid><description>&lt;p&gt;今までは AWS や GCP 上に InfluxDB の環境を用意して使っていたのですが、InfluxDB Cloud というクラウドサービスがあることを知ったので、使ってみました。&lt;br&gt;
バージョンも今までは v1 を使っていましたが、クラウドなので v2 に変わります。&lt;/p&gt;
&lt;h2 id="準備"&gt;&lt;a href="#%e6%ba%96%e5%82%99" class="header-anchor"&gt;&lt;/a&gt;準備
&lt;/h2&gt;&lt;h3 id="バケットの作成"&gt;&lt;a href="#%e3%83%90%e3%82%b1%e3%83%83%e3%83%88%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;バケットの作成
&lt;/h3&gt;&lt;p&gt;InfluxDB v1 系でいう、データベースとリテンションポリシーを合わせたようなものかなと思います。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;サイドメニューより &lt;code&gt;Load Data&lt;/code&gt; &amp;gt; &lt;code&gt;Buckets&lt;/code&gt; を選択します。&lt;/li&gt;
&lt;li&gt;画面右側の &lt;code&gt;GENERATE BUCKET&lt;/code&gt; &amp;gt; クリックします。&lt;/li&gt;
&lt;li&gt;バケット名を入力し、必要に応じてデータの保存期間を指定します（デフォルトでは 30 日経ったら古いデータが削除されます）。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="343px" data-flex-grow="143" height="454" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/12/26/influxdb-cloud/01.png" width="650"&gt;&lt;/p&gt;
&lt;h3 id="トークンの取得"&gt;&lt;a href="#%e3%83%88%e3%83%bc%e3%82%af%e3%83%b3%e3%81%ae%e5%8f%96%e5%be%97" class="header-anchor"&gt;&lt;/a&gt;トークンの取得
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;サイドメニューより &lt;code&gt;Load Data&lt;/code&gt; &amp;gt; &lt;code&gt;API Tokens&lt;/code&gt; を選択します。&lt;/li&gt;
&lt;li&gt;画面右側の &lt;code&gt;GENERATE API TOKEN&lt;/code&gt; &amp;gt; &lt;code&gt;All Access API Token&lt;/code&gt; を選択します。&lt;/li&gt;
&lt;li&gt;トークンが表示されるのでコピーします。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;コピーしたトークンは環境変数などに設定して使います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;INFLUX_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;コピーしたトークン&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="url-の取得"&gt;&lt;a href="#url-%e3%81%ae%e5%8f%96%e5%be%97" class="header-anchor"&gt;&lt;/a&gt;URL の取得
&lt;/h3&gt;&lt;p&gt;API エンドポイントとなる URL は以下で取得できます。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;画面上部のメールアドレスを選択 &amp;gt; &lt;code&gt;Settings&lt;/code&gt; をクリック&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="python-からデータを書き込む"&gt;&lt;a href="#python-%e3%81%8b%e3%82%89%e3%83%87%e3%83%bc%e3%82%bf%e3%82%92%e6%9b%b8%e3%81%8d%e8%be%bc%e3%82%80" class="header-anchor"&gt;&lt;/a&gt;Python からデータを書き込む
&lt;/h2&gt;&lt;p&gt;以下の記事を参考にしてください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/12/python-influxdb-18-influxdbclient.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/12/python-influxdb-18-influxdbclient.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;必要な情報はバケット名、トークン、URL です。&lt;/p&gt;
&lt;h2 id="ダッシュボードの作成"&gt;&lt;a href="#%e3%83%80%e3%83%83%e3%82%b7%e3%83%a5%e3%83%9c%e3%83%bc%e3%83%89%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;ダッシュボードの作成
&lt;/h2&gt;&lt;p&gt;別途記事にします。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://dev.classmethod.jp/articles/send-and-visualize-data-with-influxdb-cloud/" target="_blank" rel="noopener"
 &gt;https://dev.classmethod.jp/articles/send-and-visualize-data-with-influxdb-cloud/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] InfluxDB 1.8 で influxdb_client を使う</title><link>https://blog.ponkotools.com/posts/2022/12/21/influxdb-client/</link><pubDate>Wed, 21 Dec 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/12/21/influxdb-client/</guid><description>&lt;p&gt;python で InfluxDB v1 に対してデータの読み書きを行う際に、ayncio を使って非同期化したいなと思ったのですが、今使っているライブラリの InfluxDBClient は asyncio に対応していないようでした。&lt;/p&gt;
&lt;p&gt;代わりに influxdata 社の influx-client を使うと asyncio を使えそうだったのですが、こちらは基本的に InfluxDB v2 以降にのみ対応しているようで、Flux という言語にしか対応していません。&lt;br&gt;
InfluxDB v1 以前は InfluxQL という SQL に近い言語が使われていました。&lt;/p&gt;
&lt;p&gt;こちら、以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://rabbit-note.com/2022/09/12/influxdb-2-flux/" target="_blank" rel="noopener"
 &gt;https://rabbit-note.com/2022/09/12/influxdb-2-flux/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ただ、InfluxDB 1.7以降でも設定を変更することで Flux が使えるようになるそうです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/influxdata/influxdb-client-python#influxdb-1-8-api-compatibility" target="_blank" rel="noopener"
 &gt;https://github.com/influxdata/influxdb-client-python#influxdb-1-8-api-compatibility&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;従って、InfluxDB v1 でも Flux を有効にしたうえで、Flux でクエリを記述してデータを取得するようにすれば、asyncio を使って非同期化することができそうです。&lt;br&gt;
ちなみに、データの書き込みに関しては Flux は関係ありませんでした。&lt;/p&gt;
&lt;p&gt;以下、InfluxDB v1 の前提で書いていますが、v2 でも基本的には同じです。&lt;br&gt;
&lt;code&gt;bucket&lt;/code&gt; &lt;code&gt;token&lt;/code&gt; の指定方法が異なるだけです。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;InfluxDB 1.8.10&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="flux-言語を有効化する"&gt;&lt;a href="#flux-%e8%a8%80%e8%aa%9e%e3%82%92%e6%9c%89%e5%8a%b9%e5%8c%96%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;Flux 言語を有効化する
&lt;/h2&gt;&lt;p&gt;InfluxDB を Docker で動かしていたのですが、環境変数に以下を追加するだけで OK でした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;INFLUXDB_HTTP_FLUX_ENABLED=true
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;h3 id="データの書き込み-write_api"&gt;&lt;a href="#%e3%83%87%e3%83%bc%e3%82%bf%e3%81%ae%e6%9b%b8%e3%81%8d%e8%be%bc%e3%81%bf-write_api" class="header-anchor"&gt;&lt;/a&gt;データの書き込み (write_api)
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;import asyncio
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from influxdb_client.client.influxdb_client_async import InfluxDBClientAsync
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from influxdb_client.client.write.point import Point
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from influxdb_client.domain.write_precision import WritePrecision
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;if __name__ == &amp;#39;__main__&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; async def main():
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; url = &amp;#39;http://&amp;lt;url&amp;gt;:8086&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; username = &amp;#39;username&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; password = &amp;#39;password&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; dbname = &amp;#39;dbname&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; rpname = &amp;#39;rpname&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # https://zeppelin.apache.org/docs/0.10.1/interpreter/influxdb.html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; bucket = f&amp;#39;{dbname}/{rpname}&amp;#39; # InfluxDB 1.8 では dbname/rpname がバケット名として使われる
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; token = f&amp;#39;{username}:{password}&amp;#39; # InfluxDB 1.8 では username:password がトークンとして使われる
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; org = &amp;#34;-&amp;#34; # InfluxDB 1.8 ではよくわからん
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; data = []
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; data.append({
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#39;fields&amp;#39;: {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#39;hoge&amp;#39;: 1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#39;measurement&amp;#39;: &amp;#39;measurement&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#39;tags&amp;#39;: {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#39;hostname&amp;#39;: &amp;#39;hostname&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; points = [ Point.from_dict(i, WritePrecision.MS) for i in data ]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; async with InfluxDBClientAsync(url=url, token=token, org=org) as client:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; write_api = client.write_api()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; successfully = await write_api.write(bucket=bucket, record=points)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; print(successfully)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="データの読み込み-query_api"&gt;&lt;a href="#%e3%83%87%e3%83%bc%e3%82%bf%e3%81%ae%e8%aa%ad%e3%81%bf%e8%be%bc%e3%81%bf-query_api" class="header-anchor"&gt;&lt;/a&gt;データの読み込み (query_api)
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;import asyncio
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from influxdb_client.client.influxdb_client_async import InfluxDBClientAsync
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;if __name__ == &amp;#39;__main__&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; async def main():
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; url = &amp;#39;http://&amp;lt;url&amp;gt;:8086&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; username = &amp;#39;username&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; password = &amp;#39;password&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; dbname = &amp;#39;dbname&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; rpname = &amp;#39;rpname&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # https://zeppelin.apache.org/docs/0.10.1/interpreter/influxdb.html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; bucket = f&amp;#39;{dbname}/{rpname}&amp;#39; # InfluxDB 1.8 では dbname/rpname がバケット名として使われる
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; token = f&amp;#39;{username}:{password}&amp;#39; # InfluxDB 1.8 では username:password がトークンとして使われる
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; org = &amp;#34;-&amp;#34; # InfluxDB 1.8 ではよくわからん
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; query = f&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; from(bucket: &amp;#34;{bucket}&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; range(start: -10m)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; filter(fn:(r) =&amp;gt; r._measurement == &amp;#34;measurement&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; filter(fn: (r) =&amp;gt; r[&amp;#34;_field&amp;#34;] == &amp;#34;field&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&amp;gt; aggregateWindow(every: 1m, fn: mean, createEmpty: false)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; async with InfluxDBClientAsync(url=url, token=token, org=org) as client:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; tables = await client.query_api().query(query=query)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; for table in tables:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; print(table)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; for record in table.records:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; print (record.values)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; asyncio.run(main())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Flux については以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/riverplus/items/20456e4188a4c0f5f62d" target="_blank" rel="noopener"
 &gt;https://qiita.com/riverplus/items/20456e4188a4c0f5f62d&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://powersj.io/posts/influxdb-docker-dev/" target="_blank" rel="noopener"
 &gt;https://powersj.io/posts/influxdb-docker-dev/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/influxdata/influxdb-client-python#async-write-api" target="_blank" rel="noopener"
 &gt;https://github.com/influxdata/influxdb-client-python#async-write-api&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://influxdb-client.readthedocs.io/en/stable/api.html#queryapi" target="_blank" rel="noopener"
 &gt;https://influxdb-client.readthedocs.io/en/stable/api.html#queryapi&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Grafana から Rocket.Chat へ通知を行う</title><link>https://blog.ponkotools.com/posts/2022/12/13/grafana-rocketchat/</link><pubDate>Tue, 13 Dec 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/12/13/grafana-rocketchat/</guid><description>&lt;p&gt;Grafana 自体は Rocket.Chat に対応していませんが、Webhook を使うことで Rocket.Chat に通知できます。&lt;br&gt;
アラートの基本的な設定方法については以下を参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/11/grafana.html" target="_blank" rel="noopener"
 &gt;Grafana でアラートを設定する&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ここでは Rocket.Chat への通知の設定のみ記載します。&lt;/p&gt;
&lt;h2 id="rocketchat-側の設定"&gt;&lt;a href="#rocketchat-%e5%81%b4%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Rocket.Chat 側の設定
&lt;/h2&gt;&lt;p&gt;管理画面のメニューから &lt;code&gt;サービス連携&lt;/code&gt; を選択し、&lt;code&gt;Incoming&lt;/code&gt; で新規作成を行います。&lt;br&gt;
スクリプトを有効にし、以下のスクリプトを記入します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;class Script {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; process_incoming_request({ request }) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; let color = &amp;#34;#00FF00&amp;#34;; // green
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; switch(request.content.state) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; case &amp;#39;ok&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; color = &amp;#39;#00FF00&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; break;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; case &amp;#39;paused&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; color = &amp;#39;#666666&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; break;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; case &amp;#39;alerting&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; color = &amp;#39;#FF0000&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; break;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; case &amp;#39;pending&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; color = &amp;#39;#CCCCCC&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; break;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; case &amp;#39;no_data&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; color = &amp;#39;#333333&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; break;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; default:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; color = &amp;#39;#666666&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; return {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; content:{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; text: request.content.title,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;attachments&amp;#34;: [{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;color&amp;#34;: color,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;title&amp;#34;: request.content.title,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;title_link&amp;#34;: request.content.ruleUrl,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;text&amp;#34;: request.content.message,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;image_url&amp;#34;: request.content.imageUrl,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;その他、投稿先チャンネルや投稿ユーザーなどの基本的な設定を行います。&lt;br&gt;
Grafana の設定で Webhook URL が必要になるのでコピーしておきます。&lt;/p&gt;
&lt;h2 id="grafana-側の設定"&gt;&lt;a href="#grafana-%e5%81%b4%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Grafana 側の設定
&lt;/h2&gt;&lt;p&gt;Grafana のサイドメニューから &lt;code&gt;Alert rules&lt;/code&gt; を選択し、&lt;code&gt;Contact Points&lt;/code&gt; で以下の設定を行います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;New contact point&lt;/code&gt; をクリック&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Name&lt;/code&gt; にはわかりやすい名前を適当に入力する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Contact point type&lt;/code&gt; で &lt;code&gt;Webhook&lt;/code&gt; を選択する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Webhook URL&lt;/code&gt; に上記で取得した URL を入力する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Rocket.Chat に関する設定は以上で完了です。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gist.github.com/ATofighi/79895715ae0a8f5bdeff058a64012275" target="_blank" rel="noopener"
 &gt;https://gist.github.com/ATofighi/79895715ae0a8f5bdeff058a64012275&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Grafana から Slack へ通知を行う</title><link>https://blog.ponkotools.com/posts/2022/12/07/grafana-slack/</link><pubDate>Wed, 07 Dec 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/12/07/grafana-slack/</guid><description>&lt;p&gt;Grafana のアラートで Slack のチャンネルへ通知を行う方法です。&lt;br&gt;
アラートの基本的な設定方法については以下を参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/11/grafana.html" target="_blank" rel="noopener"
 &gt;Grafana でアラートを設定する&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ここでは Slack への通知の設定のみ記載します。&lt;/p&gt;
&lt;h2 id="webhook-url-の取得"&gt;&lt;a href="#webhook-url-%e3%81%ae%e5%8f%96%e5%be%97" class="header-anchor"&gt;&lt;/a&gt;Webhook URL の取得
&lt;/h2&gt;&lt;p&gt;まず、通知したい Slack のチャンネルの Webhook URL を取得します。
Webhook URL は、以下からワークスペースとチャンネルを指定して取得できます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://slack.com/services/new/incoming-webhook" target="_blank" rel="noopener"
 &gt;https://slack.com/services/new/incoming-webhook&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="contact-point-の設定"&gt;&lt;a href="#contact-point-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Contact Point の設定
&lt;/h2&gt;&lt;p&gt;Grafana のサイドメニューから &lt;code&gt;Alert rules&lt;/code&gt; を選択し、&lt;code&gt;Contact Points&lt;/code&gt; で以下の設定を行います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;New contact point&lt;/code&gt; をクリック&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Name&lt;/code&gt; にはわかりやすい名前を適当に入力する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Contact point type&lt;/code&gt; で &lt;code&gt;Slack&lt;/code&gt; を選択する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Webhook URL&lt;/code&gt; に上記で取得した URL を入力する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Slack に関する設定は以上です。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://fclout.hateblo.jp/entry/2020/06/20/Grafana%E3%81%8B%E3%82%89Slack%E3%81%B8%E9%80%9A%E7%9F%A5%E3%81%99%E3%82%8B" target="_blank" rel="noopener"
 &gt;https://fclout.hateblo.jp/entry/2020/06/20/Grafana%E3%81%8B%E3%82%89Slack%E3%81%B8%E9%80%9A%E7%9F%A5%E3%81%99%E3%82%8B&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Ubuntu の Emergency Mode で日本語配列のキーボードを使う</title><link>https://blog.ponkotools.com/posts/2022/12/02/ubuntu/</link><pubDate>Fri, 02 Dec 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/12/02/ubuntu/</guid><description>&lt;p&gt;Ubuntu 18.04 が emergency mode で起動した時に、キーボードの配列が日本語配列になっていなくて困ったのでメモです。&lt;/p&gt;
&lt;p&gt;以下を実行すれば日本語配列のキーボードが使えるようになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;loadkeys&lt;/span&gt; &lt;span class="n"&gt;jp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;尚、上記のコマンドを入力するために、私の環境では以下のようにキーを押す必要がありました。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: center"&gt;入力したい文字&lt;/th&gt;
 &lt;th style="text-align: center"&gt;実際に押したキー&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;l&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;k&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;o&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;o&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;a&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: center"&gt;左下の ctrl&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;d&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;s&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;k&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;j&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;e&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;e&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;y&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;y&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;s&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;a&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: center"&gt;スペース&lt;/td&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;.&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;j&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;h&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;p&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: center"&gt;&lt;code&gt;p&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;これが何の配列になっていたのかはわかりませんでした。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kledgeb.blogspot.com/2016/05/ubuntu-1604-60.html" target="_blank" rel="noopener"
 &gt;https://kledgeb.blogspot.com/2016/05/ubuntu-1604-60.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Grafana でアラートを設定する</title><link>https://blog.ponkotools.com/posts/2022/11/30/grafana-alert/</link><pubDate>Wed, 30 Nov 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/11/30/grafana-alert/</guid><description>&lt;p&gt;Grafana で任意の値が閾値を超えたら（または下回ったら）アラートを発報するように設定します。&lt;/p&gt;
&lt;p&gt;設定方法は Grafana のバージョンによって大きく異なるようですが、今回使用した Grafana 9.1.0 では、以下の３段階で設定を行うようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Alert rules&lt;/code&gt;: アラート条件の設定&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Contact points&lt;/code&gt;：通知先の登録&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Notification policy&lt;/code&gt;：アラート条件と通知先の関連付け&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Grafana 9.1.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="アラート条件の設定"&gt;&lt;a href="#%e3%82%a2%e3%83%a9%e3%83%bc%e3%83%88%e6%9d%a1%e4%bb%b6%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;アラート条件の設定
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;左のサイドメニューより、&lt;code&gt;Alerting&lt;/code&gt; &amp;gt; &lt;code&gt;Alert rules&lt;/code&gt; をクリックします。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;New alert rule&lt;/code&gt; をクリックします。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1. Set a query and alert condision&lt;/code&gt; で監視したい値や閾値を設定します。（具体的な設定例は後述します。）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2.Alert evaluation behavior&lt;/code&gt; でアラート保留状態となる時間を設定します。&lt;br&gt;
デフォルトでは１分毎に評価し、アラートを検出した後５分が経過したら通知が行われるようになっています。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3. Add details for your alert&lt;/code&gt; でこのアラートの名前や説明を記載します。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;4. Notifications&lt;/code&gt; で通知先のラベルを指定します（後述）。&lt;br&gt;
指定しなかった場合はデフォルトの通知先が使用されます（後述）。&lt;/li&gt;
&lt;li&gt;設定が完了したら画面右上の Save で保存します。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="通知先の登録"&gt;&lt;a href="#%e9%80%9a%e7%9f%a5%e5%85%88%e3%81%ae%e7%99%bb%e9%8c%b2" class="header-anchor"&gt;&lt;/a&gt;通知先の登録
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;左のサイドメニューより、&lt;code&gt;Alerting&lt;/code&gt; &amp;gt; &lt;code&gt;Contact points&lt;/code&gt; をクリックします。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;New contact points&lt;/code&gt; をクリックします。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Name&lt;/code&gt; で適当な名前を付け、&lt;code&gt;Contact point type&lt;/code&gt; で通知方法を選択します（後述）。&lt;/li&gt;
&lt;li&gt;設定が完了したら Save contact point で保存します。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="具体的な設定例"&gt;&lt;a href="#%e5%85%b7%e4%bd%93%e7%9a%84%e3%81%aa%e8%a8%ad%e5%ae%9a%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;具体的な設定例
&lt;/h3&gt;&lt;p&gt;通知先によって異なるため、別記事にまとめます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/12/grafana-slack.html" target="_blank" rel="noopener"
 &gt;Grafana から Slack へ通知を行う&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/12/grafana-rocketchat.html" target="_blank" rel="noopener"
 &gt;Grafana から Rocket.Chat へ通知を行う&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="アラート条件と通知先の関連付け"&gt;&lt;a href="#%e3%82%a2%e3%83%a9%e3%83%bc%e3%83%88%e6%9d%a1%e4%bb%b6%e3%81%a8%e9%80%9a%e7%9f%a5%e5%85%88%e3%81%ae%e9%96%a2%e9%80%a3%e4%bb%98%e3%81%91" class="header-anchor"&gt;&lt;/a&gt;アラート条件と通知先の関連付け
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;左のサイドメニューより、&lt;code&gt;Alerting&lt;/code&gt; &amp;gt; &lt;code&gt;Notification policies&lt;/code&gt; をクリックします。&lt;/li&gt;
&lt;li&gt;デフォルトの通知先の変更や、特定のラベルのアラートに対する通知先を設定します（後述）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Save policy&lt;/code&gt; をクリックして保存します。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="デフォルトの通知先を指定"&gt;&lt;a href="#%e3%83%87%e3%83%95%e3%82%a9%e3%83%ab%e3%83%88%e3%81%ae%e9%80%9a%e7%9f%a5%e5%85%88%e3%82%92%e6%8c%87%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;デフォルトの通知先を指定
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Root policy&lt;/code&gt; の右側にある Edit をクリックします。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Default contact point&lt;/code&gt; でデフォルトの通知先を指定します。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="特定のラベルに対する通知先を指定"&gt;&lt;a href="#%e7%89%b9%e5%ae%9a%e3%81%ae%e3%83%a9%e3%83%99%e3%83%ab%e3%81%ab%e5%af%be%e3%81%99%e3%82%8b%e9%80%9a%e7%9f%a5%e5%85%88%e3%82%92%e6%8c%87%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;特定のラベルに対する通知先を指定
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;code&gt;New specific policy&lt;/code&gt; をクリックします。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Add matcher&lt;/code&gt; でラベルの条件を指定し、&lt;code&gt;Contact point&lt;/code&gt; で通知先を指定します。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.cloud.global.fujitsu.com/lib/monitoringservice/jp/usersguide/capter02/alerting/alert_rule/" target="_blank" rel="noopener"
 &gt;https://doc.cloud.global.fujitsu.com/lib/monitoringservice/jp/usersguide/capter02/alerting/alert_rule/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Pytnon] pymongo で 一括処理（Bulk Method）を行う</title><link>https://blog.ponkotools.com/posts/2022/10/27/pymongo/</link><pubDate>Thu, 27 Oct 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/10/27/pymongo/</guid><description>&lt;p&gt;Bulk Method を使い前は以下のようにして一件ずつ &lt;code&gt;update_one&lt;/code&gt; で追加（更新）していました。&lt;/p&gt;
&lt;p&gt;これを BulkMethod を使って一括で処理するようにしてやります。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;initialize_ordered_bulk_op&lt;/code&gt; &lt;code&gt;initialize_unordered_bulk_op&lt;/code&gt; で初期化します。&lt;/p&gt;
&lt;p&gt;今回は &lt;code&gt;initialize_unordered_bulk_op&lt;/code&gt; を使用します。&lt;/p&gt;
&lt;p&gt;Bulk Method で &lt;code&gt;update_one&lt;/code&gt; を使うには、&lt;code&gt;find&lt;/code&gt; と &lt;code&gt;upsert&lt;/code&gt; メソッドを組み合わせるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.mongodb.com/docs/manual/reference/method/Bulk.find.upsert/" target="_blank" rel="noopener"
 &gt;https://www.mongodb.com/docs/manual/reference/method/Bulk.find.upsert/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、&lt;code&gt;update_one&lt;/code&gt; で３件のデータを追加（更新）する&lt;/p&gt;
&lt;p&gt;まずは処理しやすくするためにサンプルデータを配列で用意しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;sample_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sample_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;filter&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;camera_id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;detected_id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start_id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;update&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;label&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;person&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;captured_at&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;captured_at&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;disappeared_at&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;captured_at&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;thumbnail&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上記のデータについて、例えば以下のように処理します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pymongo&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MongoClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MongoClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mongodb://localhost:27017/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dbname&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;col_name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bulk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;initialize_unordered_bulk_op&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sample_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bulk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;filter&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_one&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;$setOnInsert&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;update&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bulk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;$setOnInsert&lt;/code&gt; については以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://crumbjp.hateblo.jp/entry/20130328/1364431871" target="_blank" rel="noopener"
 &gt;https://crumbjp.hateblo.jp/entry/20130328/1364431871&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://mgng.mugbum.info/745" target="_blank" rel="noopener"
 &gt;https://mgng.mugbum.info/745&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;レスポンスは以下のようなデータが返ってきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;&amp;#39;writeErrors&amp;#39;:&lt;/span&gt; &lt;span class="err"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;&amp;#39;writeConcernErrors&amp;#39;:&lt;/span&gt; &lt;span class="err"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;&amp;#39;nInserted&amp;#39;:&lt;/span&gt; &lt;span class="err"&gt;0,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;&amp;#39;nUpserted&amp;#39;:&lt;/span&gt; &lt;span class="err"&gt;2,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;&amp;#39;nMatched&amp;#39;:&lt;/span&gt; &lt;span class="err"&gt;1,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;&amp;#39;nModified&amp;#39;:&lt;/span&gt; &lt;span class="err"&gt;0,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;&amp;#39;nRemoved&amp;#39;:&lt;/span&gt; &lt;span class="err"&gt;0,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;&amp;#39;upserted&amp;#39;:&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;&amp;#39;index&amp;#39;:&lt;/span&gt; &lt;span class="err"&gt;1,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;&amp;#39;_id&amp;#39;:&lt;/span&gt; &lt;span class="err"&gt;ObjectId(&amp;#39;635878690bdc2e90f9e0e8bf&amp;#39;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;&amp;#39;index&amp;#39;:&lt;/span&gt; &lt;span class="err"&gt;2,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;&amp;#39;_id&amp;#39;:&lt;/span&gt; &lt;span class="err"&gt;ObjectId(&amp;#39;63588e750bdc2e90f9e0f1f2&amp;#39;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;nUpserted&lt;/code&gt; は新規に追加されたドキュメントの数です。&lt;br&gt;
&lt;code&gt;nMatched&lt;/code&gt; は &lt;code&gt;find&lt;/code&gt; の条件に一致したされたドキュメントの数です。&lt;br&gt;
&lt;code&gt;nModified&lt;/code&gt; は更新されたドキュメントの数です。&lt;br&gt;
&lt;code&gt;upserted&lt;/code&gt; は新規追加されたデータのインデックスと、MongoDB によって割り当てられた ID となります。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/4cteru/items/e6911a7c9c7645b8db13" target="_blank" rel="noopener"
 &gt;https://qiita.com/4cteru/items/e6911a7c9c7645b8db13&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://ailog.site/2021/09/15/2021/0915/" target="_blank" rel="noopener"
 &gt;https://ailog.site/2021/09/15/2021/0915/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://teratail.com/questions/297183?link=qa_related_sp" target="_blank" rel="noopener"
 &gt;https://teratail.com/questions/297183?link=qa_related_sp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>overlayroot の有効無効をシェルスクリプト化</title><link>https://blog.ponkotools.com/posts/2022/10/18/overlayroot/</link><pubDate>Tue, 18 Oct 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/10/18/overlayroot/</guid><description>&lt;p&gt;overlayroot を使ってファイルシステムを読み取り専用にしましたが、現在読み取り専用になっているのかどうかのチェックと、有効無効を簡単に切り替えられるようなスクリプトを作成してみました。&lt;/p&gt;
&lt;p&gt;overlayroot のインストールや設定方法については以下の記事を参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/04/overlayroot-ubuntu.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/04/overlayroot-ubuntu.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="overlayroot-が有効か無効かをチェック"&gt;&lt;a href="#overlayroot-%e3%81%8c%e6%9c%89%e5%8a%b9%e3%81%8b%e7%84%a1%e5%8a%b9%e3%81%8b%e3%82%92%e3%83%81%e3%82%a7%e3%83%83%e3%82%af" class="header-anchor"&gt;&lt;/a&gt;overlayroot が有効か無効かをチェック
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mount &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s1"&gt;&amp;#39;overlayroot on / type overlay&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&amp;gt; /dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;overlayroot enabled&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;overlayroot disabled&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;&amp;amp;&amp;gt; /dev/null&lt;/code&gt; は標準出力と標準エラー出力の破棄です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/ritukiii/items/b3d91e97b71ecd41d4ea" target="_blank" rel="noopener"
 &gt;https://qiita.com/ritukiii/items/b3d91e97b71ecd41d4ea&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;$?&lt;/code&gt; は直前に実行したコマンドの終了値です（0は成功、1は失敗）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/zayarwinttun/items/0dae4cb66d8f4bd2a337" target="_blank" rel="noopener"
 &gt;https://qiita.com/zayarwinttun/items/0dae4cb66d8f4bd2a337&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="overlayroot-を無効にする"&gt;&lt;a href="#overlayroot-%e3%82%92%e7%84%a1%e5%8a%b9%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;overlayroot を無効にする
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo overlayroot-chroot rm /etc/overlayroot.local.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;overlayroot-chroot&lt;/code&gt; で一時的に書き込み可能状態にして &lt;code&gt;/etc/overlayroot.local.conf&lt;/code&gt; を削除しているだけです。&lt;/p&gt;
&lt;h2 id="overlayroot-を有効にする"&gt;&lt;a href="#overlayroot-%e3%82%92%e6%9c%89%e5%8a%b9%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;overlayroot を有効にする
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;overlayroot=&amp;#34;tmpfs:recurse=0&amp;#34;&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee /etc/overlayroot.local.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;/etc/overlayroot.local.conf&lt;/code&gt; を作成して &lt;code&gt;overlayroot=&amp;quot;tmpfs:recurse=0&amp;quot;&lt;/code&gt; を記述しているだけです。&lt;/p&gt;
&lt;h2 id="サンプル"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;サンプル
&lt;/h2&gt;&lt;p&gt;以上を踏まえて作成してみたのが以下のスクリプトです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ex: ./overlayroot.sh disable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ex: ./overlayroot.sh enable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ex: ./overlayroot.sh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 現在の overlayroot の状態を取得&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mount &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s1"&gt;&amp;#39;overlayroot on / type overlay&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&amp;gt; /dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;overlay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;overlayroot enabled&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;overlay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;overlayroot disabled&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; disable &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# overlayroot を無効にする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$overlay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;disable overlayroot...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sudo overlayroot-chroot rm /etc/overlayroot.local.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;#34;\nReboot after &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;timeout&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; seconds&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sleep &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;timeout&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sudo reboot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;overlayroot already disabled&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# overlayroot を有効にする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$overlay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;overlayroot already enabled&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;enable overlayroot...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;overlayroot=&amp;#34;tmpfs:recurse=0&amp;#34;&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee /etc/overlayroot.local.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;#34;\nReboot after &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;timeout&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; seconds&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sleep &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;timeout&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sudo reboot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;#34;\nCloses after &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;timeout&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; seconds&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;timeout&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/copergit/automations/blob/a258017fd4c25a1704ba711e5921aa8c1bbc7c62/scripts/overlay/overlayroot" target="_blank" rel="noopener"
 &gt;https://github.com/copergit/automations/blob/a258017fd4c25a1704ba711e5921aa8c1bbc7c62/scripts/overlay/overlayroot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/ritukiii/items/b3d91e97b71ecd41d4ea" target="_blank" rel="noopener"
 &gt;https://qiita.com/ritukiii/items/b3d91e97b71ecd41d4ea&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/zayarwinttun/items/0dae4cb66d8f4bd2a337" target="_blank" rel="noopener"
 &gt;https://qiita.com/zayarwinttun/items/0dae4cb66d8f4bd2a337&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Docker Volume をコピー（複製）する</title><link>https://blog.ponkotools.com/posts/2022/10/14/docker/</link><pubDate>Fri, 14 Oct 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/10/14/docker/</guid><description>&lt;p&gt;Linux だと &lt;code&gt;/var/lib/docker/volumes/&amp;lt;volume_name&amp;gt;&lt;/code&gt; に保存されているため、基本的にはこれを &lt;code&gt;cp&lt;/code&gt; コマンドでコピーするだけで OK です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -p to preserve permissions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo cp -rp /var/lib/docker/volumes/source_volume /var/lib/docker/volumes/target_volume
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://zenn.dev/ciffelia/articles/docker-volume-backup-restore" target="_blank" rel="noopener"
 &gt;https://zenn.dev/ciffelia/articles/docker-volume-backup-restore&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/67567986/copy-docker-volumes" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/67567986/copy-docker-volumes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Markdown Preview Enhanced で HTML 出力に PNG 画像を base64 で埋め込む</title><link>https://blog.ponkotools.com/posts/2022/10/03/markdown-preview-enhanced/</link><pubDate>Mon, 03 Oct 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/10/03/markdown-preview-enhanced/</guid><description>&lt;p&gt;VSCode でマークダウンを書くのに Markdown Preview Enhanced を使用していますが、HTML で出力する際、SVG は base64 で埋め込まれましたが、PNG はデフォルトでは埋め込まれません。&lt;/p&gt;
&lt;p&gt;これについて、以下に説明があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://shd101wyy.github.io/markdown-preview-enhanced/#/ja-jp/html" target="_blank" rel="noopener"
 &gt;https://shd101wyy.github.io/markdown-preview-enhanced/#/ja-jp/html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;文書の最初に以下を記述すれば PNG が base64 で埋め込まれました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;html:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; embed_local_images: true
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://shd101wyy.github.io/markdown-preview-enhanced/#/ja-jp/html" target="_blank" rel="noopener"
 &gt;https://shd101wyy.github.io/markdown-preview-enhanced/#/ja-jp/html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>NTP サーバー/クライアント chrony の設定</title><link>https://blog.ponkotools.com/posts/2022/09/29/chrony/</link><pubDate>Thu, 29 Sep 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/09/29/chrony/</guid><description>&lt;p&gt;chrony を使って NTP サーバー、NTP クライアントのぞれぞれを設定してみました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;chrony 3.5&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="インストール"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;インストール
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install chrony
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="ntp-サーバーとしての設定"&gt;&lt;a href="#ntp-%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc%e3%81%a8%e3%81%97%e3%81%a6%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;NTP サーバーとしての設定
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;/etc/chrony/chrony.conf&lt;/code&gt; をエディタで編集します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo nano /etc/chrony/chrony.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="上位サーバーの無効化"&gt;&lt;a href="#%e4%b8%8a%e4%bd%8d%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc%e3%81%ae%e7%84%a1%e5%8a%b9%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;上位サーバーの無効化
&lt;/h3&gt;&lt;p&gt;17行目〜20行目をコメントアウトします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#pool ntp.ubuntu.com iburst maxsources 4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#pool 0.ubuntu.pool.ntp.org iburst maxsources 1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#pool 1.ubuntu.pool.ntp.org iburst maxsources 1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#pool 2.ubuntu.pool.ntp.org iburst maxsources 2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="認証の無効化"&gt;&lt;a href="#%e8%aa%8d%e8%a8%bc%e3%81%ae%e7%84%a1%e5%8a%b9%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;認証の無効化
&lt;/h3&gt;&lt;p&gt;24行目をコメントアウトします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#keyfile /etc/chrony/chrony.keys
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="アクセス許可"&gt;&lt;a href="#%e3%82%a2%e3%82%af%e3%82%bb%e3%82%b9%e8%a8%b1%e5%8f%af" class="header-anchor"&gt;&lt;/a&gt;アクセス許可
&lt;/h3&gt;&lt;p&gt;特定のセグメントからのみアクセスを許可したい場合は以下のように追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Allow NTP client access from local network.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;allow 192.168.4.0/24
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;全セグメントから許可シたい場合は &lt;code&gt;allow&lt;/code&gt; とだけ記載するようです。&lt;/p&gt;
&lt;h3 id="上位の-ntp-サーバーがいなくても同期を取れるようにする"&gt;&lt;a href="#%e4%b8%8a%e4%bd%8d%e3%81%ae-ntp-%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc%e3%81%8c%e3%81%84%e3%81%aa%e3%81%8f%e3%81%a6%e3%82%82%e5%90%8c%e6%9c%9f%e3%82%92%e5%8f%96%e3%82%8c%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;上位の NTP サーバーがいなくても同期を取れるようにする
&lt;/h3&gt;&lt;p&gt;以下を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Serve time even if not synchronized to a time source.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;local stratum 5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="再起動"&gt;&lt;a href="#%e5%86%8d%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;再起動
&lt;/h3&gt;&lt;p&gt;設定が完了したら chrony を再起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart chrony
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="ntp-クライアントとしての設定"&gt;&lt;a href="#ntp-%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e3%81%a8%e3%81%97%e3%81%a6%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;NTP クライアントとしての設定
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;/etc/chrony/chrony.conf&lt;/code&gt; をエディタで編集します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo nano /etc/chrony/chrony.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;17行目〜20行目をコメントアウトし、&lt;code&gt;pool &amp;lt;NTPサーバーのIPアドレス&amp;gt; iburst&amp;gt;&lt;/code&gt; を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#pool ntp.ubuntu.com iburst maxsources 4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#pool 0.ubuntu.pool.ntp.org iburst maxsources 1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#pool 1.ubuntu.pool.ntp.org iburst maxsources 1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#pool 2.ubuntu.pool.ntp.org iburst maxsources 2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pool 192.168.0.10 iburst
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="時刻同期について"&gt;&lt;a href="#%e6%99%82%e5%88%bb%e5%90%8c%e6%9c%9f%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6" class="header-anchor"&gt;&lt;/a&gt;時刻同期について
&lt;/h3&gt;&lt;p&gt;以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.bigbang.mydns.jp/chrony-x.htm" target="_blank" rel="noopener"
 &gt;https://www.bigbang.mydns.jp/chrony-x.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://go-journey.club/archives/12037" target="_blank" rel="noopener"
 &gt;https://go-journey.club/archives/12037&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;chrony は iburst オプションの付いた NTP サーバーに対して、起動直後に短い間隔で4回問い合わせをするそうです。
また、デフォルトでは &lt;code&gt;makestep 1 3&lt;/code&gt; の設定がありますが、これは chrony の起動時に、1.0 秒以上時刻ずれが 3 回続いた場合、step モードで一気に時刻補正をするという意味だそうです。
そうでない場合は slew モードで少しずつ時刻補正を行うそうです。&lt;/p&gt;
&lt;h3 id="再起動-1"&gt;&lt;a href="#%e5%86%8d%e8%b5%b7%e5%8b%95-1" class="header-anchor"&gt;&lt;/a&gt;再起動
&lt;/h3&gt;&lt;p&gt;設定が完了したら chrony を再起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart chrony
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="確認"&gt;&lt;a href="#%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;確認
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;chronyc sources&lt;/code&gt; を実行し、サーバー名の最初に &lt;code&gt;*&lt;/code&gt; と表示されていれば同期が取れています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ chronyc sources
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;210&lt;/span&gt; Number of &lt;span class="nv"&gt;sources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MS Name/IP address Stratum Poll Reach LastRx Last &lt;span class="nv"&gt;sample&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;===============================================================================&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;^* 192.168.0.10 &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="m"&gt;377&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt; -7277ns&lt;span class="o"&gt;[&lt;/span&gt;-2447ns&lt;span class="o"&gt;]&lt;/span&gt; +/- 41us
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="ちょっとはまったところ"&gt;&lt;a href="#%e3%81%a1%e3%82%87%e3%81%a3%e3%81%a8%e3%81%af%e3%81%be%e3%81%a3%e3%81%9f%e3%81%a8%e3%81%93%e3%82%8d" class="header-anchor"&gt;&lt;/a&gt;ちょっとはまったところ
&lt;/h2&gt;&lt;p&gt;きちんと同期がとれているか確認するために、サーバー側の日時を Ubuntu の GUI で変更し、クライアントの PC を再起動してみましたが、同期されませんでした。&lt;br&gt;
何でだろうと思っていたら、日時を GUI で変更したときに chrony のサービスが停止していました。&lt;/p&gt;
&lt;p&gt;chrony が動いているかどうかは以下のコマンドで確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl status chrony
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;もし chrony が停止していた場合は、以下のコマンドで起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl start chrony
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この状態でクライアントの PC を再起動したら、起動時に日時が同期されました。&lt;/p&gt;
&lt;p&gt;もし PC 再起動後に chrony が停止していた場合は有効化されていないので、以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; chrony
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.isoroot.jp/blog/2844/" target="_blank" rel="noopener"
 &gt;https://www.isoroot.jp/blog/2844/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://tech-lab.sios.jp/archives/11247" target="_blank" rel="noopener"
 &gt;https://tech-lab.sios.jp/archives/11247&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.bigbang.mydns.jp/chrony-x.htm" target="_blank" rel="noopener"
 &gt;https://www.bigbang.mydns.jp/chrony-x.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://go-journey.club/archives/12037" target="_blank" rel="noopener"
 &gt;https://go-journey.club/archives/12037&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] yaml 内の環境変数を展開して読み込む</title><link>https://blog.ponkotools.com/posts/2022/09/28/python-yaml/</link><pubDate>Wed, 28 Sep 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/09/28/python-yaml/</guid><description>&lt;p&gt;&lt;code&gt;pyaml-env&lt;/code&gt; を使うと簡単にできました。&lt;/p&gt;
&lt;h2 id="インストール"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;インストール
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pip install pyaml-env
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="サンプル"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;サンプル
&lt;/h2&gt;&lt;p&gt;yaml 内では、環境変数を展開したい行に &lt;code&gt;!ENV&lt;/code&gt; を書くようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="l"&gt;ENV &amp;#39;http://${HOST}:${PORT}&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pyaml_env&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;parse_config&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parse_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;sample.yaml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.wenyanet.com/opensource/ja/61162b748356b8749f1e4126.html" target="_blank" rel="noopener"
 &gt;https://www.wenyanet.com/opensource/ja/61162b748356b8749f1e4126.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>InfluxDB のコマンド (InfluxQL)</title><link>https://blog.ponkotools.com/posts/2022/09/22/influxdb/</link><pubDate>Thu, 22 Sep 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/09/22/influxdb/</guid><description>&lt;p&gt;ちょっと何かしたいというときに毎回コマンドを調べているので、個人的によく使うコマンドをまとめてみました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;InfluxDB 1.8.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="事前知識"&gt;&lt;a href="#%e4%ba%8b%e5%89%8d%e7%9f%a5%e8%ad%98" class="header-anchor"&gt;&lt;/a&gt;事前知識
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;influx&lt;/code&gt; コマンドで DB との対話モードとなります。&lt;br&gt;
この状態でコマンドを実行していきます。&lt;br&gt;
尚、対話モードに入らずに以下のようにしてコマンドを実行することもできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ influx -execute &lt;span class="s2"&gt;&amp;#34;コマンド&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下、対話モードになっている前提でコマンドのみ記載します。&lt;/p&gt;
&lt;h2 id="データベースの作成"&gt;&lt;a href="#%e3%83%87%e3%83%bc%e3%82%bf%e3%83%99%e3%83%bc%e3%82%b9%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;データベースの作成
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.influxdata.com/influxdb/v1.8/query_language/spec/#create-database" target="_blank" rel="noopener"
 &gt;https://docs.influxdata.com/influxdb/v1.8/query_language/spec/#create-database&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;create database &amp;lt;データベース名&amp;gt;&lt;/code&gt; を実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; create database sampledb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="データベースの表示"&gt;&lt;a href="#%e3%83%87%e3%83%bc%e3%82%bf%e3%83%99%e3%83%bc%e3%82%b9%e3%81%ae%e8%a1%a8%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;データベースの表示
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.influxdata.com/influxdb/v1.8/query_language/spec/#show-databases" target="_blank" rel="noopener"
 &gt;https://docs.influxdata.com/influxdb/v1.8/query_language/spec/#show-databases&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;show databases&lt;/code&gt; を実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; show databases
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;name: databases
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;name
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sampledb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;_internal
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="リテンションポリシーの作成"&gt;&lt;a href="#%e3%83%aa%e3%83%86%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%b3%e3%83%9d%e3%83%aa%e3%82%b7%e3%83%bc%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;リテンションポリシーの作成
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.influxdata.com/influxdb/v1.8/query_language/spec/#create-retention-policy" target="_blank" rel="noopener"
 &gt;https://docs.influxdata.com/influxdb/v1.8/query_language/spec/#create-retention-policy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;create retention policy &amp;lt;リテンションポリシー名&amp;gt; on &amp;lt;データベース名&amp;gt;&lt;/code&gt; を実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; create retention policy samplerp on sampledb duration 30d replication &lt;span class="m"&gt;1&lt;/span&gt; default
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;duration&lt;/code&gt; : 保存期間を指定
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.influxdata.com/influxdb/v1.8/query_language/spec/#durations" target="_blank" rel="noopener"
 &gt;https://docs.influxdata.com/influxdb/v1.8/query_language/spec/#durations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;replication&lt;/code&gt; : でレプリケーション数を指定&lt;/li&gt;
&lt;li&gt;&lt;code&gt;default&lt;/code&gt; : このリテンションポリシーをデフォルトにする&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="リテンションポリシーの表示"&gt;&lt;a href="#%e3%83%aa%e3%83%86%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%b3%e3%83%9d%e3%83%aa%e3%82%b7%e3%83%bc%e3%81%ae%e8%a1%a8%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;リテンションポリシーの表示
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.influxdata.com/influxdb/v1.8/query_language/spec/#show-retention-policies" target="_blank" rel="noopener"
 &gt;https://docs.influxdata.com/influxdb/v1.8/query_language/spec/#show-retention-policies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;use &amp;lt;データベース名&amp;gt;&lt;/code&gt; でデータベースを選択し、&lt;code&gt;show retention policies&lt;/code&gt; で表示します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; use sampledb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Using database sampledb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; show retention policies
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;name duration shardGroupDuration replicaN default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---- -------- ------------------ -------- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;autogen 0s 168h0m0s &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;samplerp 720h0m0s 24h0m0s &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="リテンションポリシーの保存期間を変更"&gt;&lt;a href="#%e3%83%aa%e3%83%86%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%b3%e3%83%9d%e3%83%aa%e3%82%b7%e3%83%bc%e3%81%ae%e4%bf%9d%e5%ad%98%e6%9c%9f%e9%96%93%e3%82%92%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;リテンションポリシーの保存期間を変更
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.influxdata.com/influxdb/v1.8/query_language/spec/#alter-retention-policy" target="_blank" rel="noopener"
 &gt;https://docs.influxdata.com/influxdb/v1.8/query_language/spec/#alter-retention-policy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;alter retention policy &amp;lt;リテンションポリシー名&amp;gt; on &amp;lt;データベース名&amp;gt; duration &amp;lt;保存期間&amp;gt;&lt;/code&gt; を実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; alter retention policy samplerp on sampledb duration 180d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;show retention policies&lt;/code&gt; で変わったことを確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; show retention policies
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;name duration shardGroupDuration replicaN default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---- -------- ------------------ -------- -------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;autogen 0s 168h0m0s &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;samplerp 4320h0m0s 24h0m0s &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>TIG Stack を動かしてみる</title><link>https://blog.ponkotools.com/posts/2022/09/16/tigstack/</link><pubDate>Fri, 16 Sep 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/09/16/tigstack/</guid><description>&lt;p&gt;サーバーリソースのメトリクスやログの収集・保存・可視化・アラートを行うためにTIG Stack (Telegraf, InfluxDB, Grafana) を使って一通り設定してみました。&lt;/p&gt;
&lt;p&gt;一応、以前にも記事は書いていますが、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/12/telegraf-influxdb-garafana.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2021/12/telegraf-influxdb-garafana.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ちょっと情報が古くなっていたので、アップデートし、さらに出来る限り設定を自動化しました。&lt;/p&gt;
&lt;h2 id="予備知識"&gt;&lt;a href="#%e4%ba%88%e5%82%99%e7%9f%a5%e8%ad%98" class="header-anchor"&gt;&lt;/a&gt;予備知識
&lt;/h2&gt;&lt;p&gt;時系列とは何ぞや？ TICK スタックとは何ぞや？みたいな話が以下に載ってました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.influxdata.com/blog/influxdb-the-platform-for-time-series-data/" target="_blank" rel="noopener"
 &gt;https://www.influxdata.com/blog/influxdb-the-platform-for-time-series-data/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.influxdata.com/blog/introduction-to-influxdatas-influxdb-and-tick-stack/" target="_blank" rel="noopener"
 &gt;https://www.influxdata.com/blog/introduction-to-influxdatas-influxdb-and-tick-stack/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://medium.com/yavar/influxdb-tick-stack-part1-28bd04d10a18" target="_blank" rel="noopener"
 &gt;https://medium.com/yavar/influxdb-tick-stack-part1-28bd04d10a18&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.influxdata.com/integration/syslog/" target="_blank" rel="noopener"
 &gt;https://www.influxdata.com/integration/syslog/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;p&gt;TIG Stack は全て Docker で動かします。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;Docker 20.10.12&lt;/li&gt;
&lt;li&gt;Telegraf 1.23.0&lt;/li&gt;
&lt;li&gt;InfluxDB 1.8.10&lt;/li&gt;
&lt;li&gt;Grafana 9.1.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="各ツールの役割"&gt;&lt;a href="#%e5%90%84%e3%83%84%e3%83%bc%e3%83%ab%e3%81%ae%e5%bd%b9%e5%89%b2" class="header-anchor"&gt;&lt;/a&gt;各ツールの役割
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;ツール&lt;/th&gt;
 &lt;th style="text-align: left"&gt;役割&lt;/th&gt;
 &lt;th&gt;Docker イメージ&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Telegraf&lt;/td&gt;
 &lt;td style="text-align: left"&gt;データの収集&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://hub.docker.com/_/telegraf" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/_/telegraf&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;InfluxDB&lt;/td&gt;
 &lt;td style="text-align: left"&gt;データの保存（時系列データベース）&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://hub.docker.com/_/influxdb" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/_/influxdb&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Grafana&lt;/td&gt;
 &lt;td style="text-align: left"&gt;データの可視化（UI）&lt;/td&gt;
 &lt;td&gt;&lt;a class="link" href="https://hub.docker.com/r/grafana/grafana/" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/r/grafana/grafana/&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;上記の Docker hub のページに各ツールの起動方法や設定方法などが一通り載っているので、それを参考に設定していきます。&lt;/p&gt;
&lt;h2 id="telegraf-の設定"&gt;&lt;a href="#telegraf-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Telegraf の設定
&lt;/h2&gt;&lt;p&gt;まずは設定ファイルの雛型（デフォルトの設定ファイル）を取得します。&lt;br&gt;
Telegraf の Docker コンテナを起動し、コンテナ内から設定ファイルをホストにコピーしてきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run --rm telegraf telegraf config &amp;gt; telegraf.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この &lt;code&gt;telegraf.conf&lt;/code&gt; を取得したいデータに応じて編集します。&lt;br&gt;
これについてはいろいろあるので、別記事にまとめました。&lt;/p&gt;
&lt;h2 id="docker-composeyml"&gt;&lt;a href="#docker-composeyml" class="header-anchor"&gt;&lt;/a&gt;docker-compose.yml
&lt;/h2&gt;&lt;p&gt;設定ファイルが必要なのは Telegraf だけなので、ここで TIG Stack を起動する &lt;code&gt;docker-compose.yml&lt;/code&gt; のサンプルを載せます。&lt;br&gt;
前提として、&lt;code&gt;tigstack&lt;/code&gt; というネットワークを共通に使用しているので、以下のコマンドであらかじめ作成しておく必要があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker network create tigstack
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下、&lt;code&gt;docker-compose.yml&lt;/code&gt; のサンプルです。解説などは後述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="telegraf-について"&gt;&lt;a href="#telegraf-%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6" class="header-anchor"&gt;&lt;/a&gt;Telegraf について
&lt;/h3&gt;&lt;h4 id="gpu-の情報取得について"&gt;&lt;a href="#gpu-%e3%81%ae%e6%83%85%e5%a0%b1%e5%8f%96%e5%be%97%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6" class="header-anchor"&gt;&lt;/a&gt;GPU の情報取得について
&lt;/h4&gt;&lt;p&gt;NVIDIA の GPU の情報を取得するために以下を指定しています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;NVIDIA_VISIBLE_DEVICES=all&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;NVIDIA_DRIVER_CAPABILITIES=all&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;reservations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;gpu]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;/usr/bin/nvidia-smi:/usr/bin/nvidia-smi:ro&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これについては以下の記事を参照してください。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/usr/bin/nvidia-smi&lt;/code&gt; のパスは環境によっては異なるかもしれません。&lt;/p&gt;
&lt;h4 id="docker-の情報取得について"&gt;&lt;a href="#docker-%e3%81%ae%e6%83%85%e5%a0%b1%e5%8f%96%e5%be%97%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6" class="header-anchor"&gt;&lt;/a&gt;Docker の情報取得について
&lt;/h4&gt;&lt;p&gt;Docker の情報を取得するためには &lt;code&gt;/var/run/docker.sock&lt;/code&gt; をマウントする必要があります。&lt;br&gt;
さらに Telegraf の実行ユーザーが docker.sock にアクセスできるように、&lt;code&gt;user&lt;/code&gt; を設定する必要があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${TELEGRAF_UID_GID:?}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これについては以下の記事を参照してください。&lt;/p&gt;
&lt;h4 id="ホスト名の指定"&gt;&lt;a href="#%e3%83%9b%e3%82%b9%e3%83%88%e5%90%8d%e3%81%ae%e6%8c%87%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;ホスト名の指定
&lt;/h4&gt;&lt;p&gt;Telegraf がメトリクスを InfluxDB に記録する際、ホスト名も記録されますが、Docker コンテナのホスト名はデフォルトだとランダムな値となり、このままでよくわからないので、設定します。&lt;br&gt;
ここではホストマシンと同じホスト名を指定しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hostname: ${HOSTNAME:?}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これについては以下の記事を参照してください。&lt;/p&gt;
&lt;h3 id="influxdb-について"&gt;&lt;a href="#influxdb-%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6" class="header-anchor"&gt;&lt;/a&gt;InfluxDB について
&lt;/h3&gt;&lt;p&gt;初回起動時にデフォルトのリテンションポリシーを設定するために以下を指定しています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DOCKER_INFLUXDB_INIT_MODE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;setup&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DOCKER_INFLUXDB_INIT_RETENTION&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;10d&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>[Python] psutil を使おうとしたら `command 'aarch64-linux-gnu-gcc' failed with exit status 1` のエラーがでた</title><link>https://blog.ponkotools.com/posts/2022/09/13/psutil/</link><pubDate>Tue, 13 Sep 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/09/13/psutil/</guid><description>&lt;p&gt;arm 系の CPU 環境において、Ubuntu のイメージを使った Docker コンテナ内で、python の psutil を使ってストレージの情報を取得しようとしたところ、psutil のインストール時に以下のエラーが表示されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;error: command &amp;#39;aarch64-linux-gnu-gcc&amp;#39; failed with exit status 1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;crossbuild-essential-arm64&lt;/code&gt; と &lt;code&gt;python3-dev&lt;/code&gt; をインストールすれば解決しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install crossbuild-essential-arm64 python3-dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/yuta_vamdemic/items/277a5a692840d06c4cd9" target="_blank" rel="noopener"
 &gt;https://qiita.com/yuta_vamdemic/items/277a5a692840d06c4cd9&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>docker-compose のアップデート方法</title><link>https://blog.ponkotools.com/posts/2022/09/12/docker-compose/</link><pubDate>Mon, 12 Sep 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/09/12/docker-compose/</guid><description>&lt;p&gt;apt でインストールした docker-compose のバージョンが古いので、手動でアップデートする方法です。&lt;/p&gt;
&lt;p&gt;docker-compose のリリースビルド一覧は以下で確認できます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/docker/compose/releases" target="_blank" rel="noopener"
 &gt;https://github.com/docker/compose/releases&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 現在インストールされている docker-compose をアンインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;remove&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compose&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# カーネル名を小文字にするため一度変数 kernel に代入&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;kernel&lt;/span&gt;&lt;span class="o"&gt;=$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uname&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ダウンロード&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;wget&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compose&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;compose&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;releases&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;download&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compose&lt;/span&gt;&lt;span class="o"&gt;-$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;,,}&lt;/span&gt;&lt;span class="o"&gt;-$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uname&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 実行権限の付与&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;chmod&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compose&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一応これで intel 系と arm 系で上手くいくことは確認しました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/docker/compose/releases" target="_blank" rel="noopener"
 &gt;https://github.com/docker/compose/releases&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] コンテナ内の実行ユーザーをホストのユーザーと合わせる</title><link>https://blog.ponkotools.com/posts/2022/08/30/docker/</link><pubDate>Tue, 30 Aug 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/08/30/docker/</guid><description>&lt;p&gt;Docker コンテナにホストのディレクトリをマウントしている場合、コンテナ内の実行ユーザーとホストのユーザーが一致していないと、コンテナ内で作成されたファイルにアクセス権限がなくて困ることがあります。&lt;/p&gt;
&lt;p&gt;これはコンテナ内の実行ユーザーをホストのユーザーと合わせることで解決できますが、じゃあユーザーの指定はどうするのが一番良いか？
ということで、以下の記事がとても参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/yohm/items/047b2e68d008ebb0f001" target="_blank" rel="noopener"
 &gt;https://qiita.com/yohm/items/047b2e68d008ebb0f001&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ほとんどの場合、以下で上手く行くそうです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run -it &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /etc/group:/etc/group:ro &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /etc/passwd:/etc/passwd:ro &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -u &lt;span class="k"&gt;$(&lt;/span&gt;id -u &lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;:&lt;span class="k"&gt;$(&lt;/span&gt;id -g &lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ubuntu bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;私の場合もこれで上手く行きました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/yohm/items/047b2e68d008ebb0f001" target="_blank" rel="noopener"
 &gt;https://qiita.com/yohm/items/047b2e68d008ebb0f001&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Telegraf で CPU の温度を取得する</title><link>https://blog.ponkotools.com/posts/2022/08/24/telegraf/</link><pubDate>Wed, 24 Aug 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/08/24/telegraf/</guid><description>&lt;p&gt;タイトルの通りです。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="cpu-の温度観測プローブを調べる"&gt;&lt;a href="#cpu-%e3%81%ae%e6%b8%a9%e5%ba%a6%e8%a6%b3%e6%b8%ac%e3%83%97%e3%83%ad%e3%83%bc%e3%83%96%e3%82%92%e8%aa%bf%e3%81%b9%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;CPU の温度観測プローブを調べる
&lt;/h2&gt;&lt;p&gt;以下の記事が参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/koara-local/items/1fac13704123717f5cc8" target="_blank" rel="noopener"
 &gt;https://qiita.com/koara-local/items/1fac13704123717f5cc8&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;/sys/class/thermal&lt;/code&gt; に &lt;code&gt;thermal_zone0&lt;/code&gt; 〜 &lt;code&gt;thermal_zone3&lt;/code&gt; の４つのディレクトリがあり、このうちのどれかが CPU の温度観測用のファイルのようです。&lt;br&gt;
これらの中にある &lt;code&gt;type&lt;/code&gt; ファイルを見ることで、何の温度を表しているかが分かるようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat /sys/class/thermal/thermal_zone0/type
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;acpitz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat /sys/class/thermal/thermal_zone1/type
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;acpitz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat /sys/class/thermal/thermal_zone2/type
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pch_skylake
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat /sys/class/thermal/thermal_zone3/type
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;x86_pkg_temp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;どうやら私の環境では &lt;code&gt;thermal_zone3&lt;/code&gt; が CPU の温度のようです。&lt;br&gt;
なので、&lt;code&gt;/sys/class/thermal/thermal_zone3/temp&lt;/code&gt; を見ることで CPU の温度が取得できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat /sys/class/thermal/thermal_zone3/temp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;35000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;1000 倍された値が表示されるので、上記の場合 35℃ です。&lt;/p&gt;
&lt;h2 id="telegraf-の設定"&gt;&lt;a href="#telegraf-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Telegraf の設定
&lt;/h2&gt;&lt;p&gt;上記のファイルを監視するように、&lt;code&gt;telegraf.conf&lt;/code&gt; に以下を記述するだけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;inputs.file&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/sys/class/thermal/thermal_zone3/temp&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;name_override&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;cpu_temperature&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;data_format&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;data_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;integer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/koara-local/items/1fac13704123717f5cc8" target="_blank" rel="noopener"
 &gt;https://qiita.com/koara-local/items/1fac13704123717f5cc8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://goozenlab.github.io/blog/2019/08/telegraf-pi-install/" target="_blank" rel="noopener"
 &gt;https://goozenlab.github.io/blog/2019/08/telegraf-pi-install/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.htkyama.org/telegraf_influxdb_grafana" target="_blank" rel="noopener"
 &gt;https://blog.htkyama.org/telegraf_influxdb_grafana&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>シェルスクリプトをダブルクリックで端末内で実行する</title><link>https://blog.ponkotools.com/posts/2022/08/23/shell/</link><pubDate>Tue, 23 Aug 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/08/23/shell/</guid><description>&lt;p&gt;Ubuntu 20.04 にて、デスクトップに置いたシェルスクリプトファイルをダブルクリックで実行し、かつ端末内で実行する方法です。&lt;br&gt;
結構はまったのでメモしておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gnome-terminal -- bash -c &lt;span class="s2"&gt;&amp;#34;echo sample;sleep 5&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;端末がすぐ閉じるのを防ぐために &lt;code&gt;sleep 5&lt;/code&gt; を入れています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gnome-terminal -- bash -c &lt;span class="s2"&gt;&amp;#34;/home/username/sample.sh;sleep 5&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://askubuntu.com/questions/1259265/make-gnome-terminal-request-user-confirmation-before-close" target="_blank" rel="noopener"
 &gt;https://askubuntu.com/questions/1259265/make-gnome-terminal-request-user-confirmation-before-close&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>overlayroot 環境内で docker を使う方法</title><link>https://blog.ponkotools.com/posts/2022/08/19/overlayroot/</link><pubDate>Fri, 19 Aug 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/08/19/overlayroot/</guid><description>&lt;p&gt;overlayroot でルートファイルシステムを読み取り専用にしたところ、docker が使えなくなりました。&lt;/p&gt;
&lt;p&gt;OS は Ubuntu 20.04 です。&lt;br&gt;
overlayroot を有効にする方法などについては以前の記事を参考にしてください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/04/overlayroot-ubuntu.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/04/overlayroot-ubuntu.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="問題点"&gt;&lt;a href="#%e5%95%8f%e9%a1%8c%e7%82%b9" class="header-anchor"&gt;&lt;/a&gt;問題点
&lt;/h2&gt;&lt;p&gt;Docker がインストールされている環境で、overlayroot でルートファイルシステムを読み取り専用にした場合、docker コマンドを実行すると以下のようなエラーが発生します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;いろいろ調べてみた結果、基本的に overlayroot が有効な状態では docker は使えないようです。&lt;br&gt;
一応以下にあるやり方で docker コンテナを立ち上げるところまではできました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://superuser.com/questions/1526682/docker-in-overlayroot-environment-invalid-cross-device-link" target="_blank" rel="noopener"
 &gt;https://superuser.com/questions/1526682/docker-in-overlayroot-environment-invalid-cross-device-link&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/docker/for-linux/issues/775" target="_blank" rel="noopener"
 &gt;https://github.com/docker/for-linux/issues/775&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;しかし、そもそも Docker ボリュームには DB のデータなどを逐次格納していっているので、tmpfs 上（＝メモリ上）だとメモリがすぐ枯渇してしまいそうです。&lt;br&gt;
また、Docker コンテナ・イメージをアップデートしたい場合にも困ります。&lt;/p&gt;
&lt;p&gt;というわけで、少なくとも &lt;code&gt;/var/lib/docker&lt;/code&gt; の領域はパーティションを分けるしかないじゃないかというところに行き着きました。&lt;br&gt;
以下のページでも書き込み可能としたい場合はパーティションを分ける方法が紹介されています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://armadillo.atmark-techno.com/index.php/blog/10899/8648" target="_blank" rel="noopener"
 &gt;https://armadillo.atmark-techno.com/index.php/blog/10899/8648&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、Docker に関するベストプラクティスでも、コンテナ用にパーティションを分けるとあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.creationline.com/lab/aquasecurity/43087" target="_blank" rel="noopener"
 &gt;https://www.creationline.com/lab/aquasecurity/43087&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;その上で、Docker コンテナも read-only で起動すれば、ルートファイルシステムだけでなく Docker コンテナも保護できそうです。&lt;/p&gt;
&lt;h2 id="対処方法"&gt;&lt;a href="#%e5%af%be%e5%87%a6%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;対処方法
&lt;/h2&gt;&lt;p&gt;とりあえず以下のようにパーティションを分けることで overlayroot と docker の共存ができました。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;パス&lt;/th&gt;
 &lt;th&gt;マウントポイント&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;/dev/sda1&lt;/td&gt;
 &lt;td&gt;EFI システムパーティション&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;/dev/sda2&lt;/td&gt;
 &lt;td&gt;/&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;/dev/sda3&lt;/td&gt;
 &lt;td&gt;/var&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;この状態で overlayroot をインストールし、&lt;code&gt;/etc/overlayroot.local.conf&lt;/code&gt; に &lt;code&gt;overlayroot=&amp;quot;tmpfs:recurse=0&amp;quot;&lt;/code&gt; を記載します。
コマンド一発でやる場合は以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;overlayroot=&amp;#34;tmpfs:recurse=0&amp;#34;&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee -a /etc/overlayroot.local.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;overlayroot のインストールや設定については以前の記事を参考にしてください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/04/overlayroot-ubuntu.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/04/overlayroot-ubuntu.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回はルートファイルシステムのみを読み取り専用にするので、&lt;code&gt;tmpfs:recurse=0&lt;/code&gt; を指定するらしいです。&lt;br&gt;
以下が参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gihyo.jp/admin/serial/01/ubuntu-recipe/0568" target="_blank" rel="noopener"
 &gt;https://gihyo.jp/admin/serial/01/ubuntu-recipe/0568&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これで再起動すれば、ルートファイルシステムのみが読み取り専用となり、&lt;code&gt;/var&lt;/code&gt; は読み書き可能な状態となります。&lt;br&gt;
docker も普通に使えました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://superuser.com/questions/1526682/docker-in-overlayroot-environment-invalid-cross-device-link" target="_blank" rel="noopener"
 &gt;https://superuser.com/questions/1526682/docker-in-overlayroot-environment-invalid-cross-device-link&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/docker/for-linux/issues/775" target="_blank" rel="noopener"
 &gt;https://github.com/docker/for-linux/issues/775&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://armadillo.atmark-techno.com/index.php/blog/10899/8648" target="_blank" rel="noopener"
 &gt;https://armadillo.atmark-techno.com/index.php/blog/10899/8648&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://armadillo.atmark-techno.com/forum/armadillo/7894" target="_blank" rel="noopener"
 &gt;https://armadillo.atmark-techno.com/forum/armadillo/7894&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://spin.atomicobject.com/2015/03/10/protecting-ubuntu-root-filesystem/" target="_blank" rel="noopener"
 &gt;https://spin.atomicobject.com/2015/03/10/protecting-ubuntu-root-filesystem/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kurosute.com/raspberrypi-overlayroot/" target="_blank" rel="noopener"
 &gt;https://kurosute.com/raspberrypi-overlayroot/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/kakkie/items/c4a9a2f2a9e4e802ca0b" target="_blank" rel="noopener"
 &gt;https://qiita.com/kakkie/items/c4a9a2f2a9e4e802ca0b&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://gihyo.jp/admin/serial/01/ubuntu-recipe/0568" target="_blank" rel="noopener"
 &gt;https://gihyo.jp/admin/serial/01/ubuntu-recipe/0568&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Rocket.Chat の REST API でダイレクトメッセージを送る</title><link>https://blog.ponkotools.com/posts/2022/08/17/rocketchat/</link><pubDate>Wed, 17 Aug 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/08/17/rocketchat/</guid><description>&lt;p&gt;アプリケーションから Rocket.Chat のユーザーに対してダイレクトメッセージを送りたかったので、調べてみたら、REST API を使うことでできました。&lt;/p&gt;
&lt;p&gt;使用した API の仕様は以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://developer.rocket.chat/reference/api/rest-api/endpoints/core-endpoints/chat-endpoints/postmessage" target="_blank" rel="noopener"
 &gt;https://developer.rocket.chat/reference/api/rest-api/endpoints/core-endpoints/chat-endpoints/postmessage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例えば Windows の場合、以下のようなコマンドで動作を確認できました。&lt;br&gt;
（ユーザー名の部分だけ変更してください。）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl.exe -X POST^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &amp;#34;X-Auth-Token: &amp;lt;Token&amp;gt;&amp;#34;^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &amp;#34;X-User-Id: &amp;lt;User-Id&amp;gt;&amp;#34;^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &amp;#34;Content-type:application/json&amp;#34;^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; http://rocketchat-url/api/v1/chat.postMessage^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -d &amp;#34;{\&amp;#34;channel\&amp;#34;: \&amp;#34;@ユーザー名\&amp;#34;, \&amp;#34;msg\&amp;#34;: \&amp;#34;This is a direct message!\&amp;#34; }&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Token&lt;/code&gt; と &lt;code&gt;User-Id&lt;/code&gt; は、マイアカウント &amp;gt; パーソナルアクセストークン から作成できます。&lt;br&gt;
REST API の実行権限のあるアカウントで作成する必要があります。&lt;/p&gt;
&lt;p&gt;メッセージの内容については上記の API 仕様を参照してください。&lt;br&gt;
例えば、以下のようにして通知者名とアイコンを変更することができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl.exe -X POST^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &amp;#34;X-Auth-Token: &amp;lt;Token&amp;gt;&amp;#34;^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &amp;#34;X-User-Id: &amp;lt;User-Id&amp;gt;&amp;#34;^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &amp;#34;Content-type:application/json&amp;#34;^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; http://rocketchat-url/api/v1/chat.postMessage^
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -d &amp;#34;{\&amp;#34;channel\&amp;#34;: \&amp;#34;@ユーザー名\&amp;#34;, \&amp;#34;msg\&amp;#34;: \&amp;#34;This is a direct message!\&amp;#34;, \&amp;#34;alias\&amp;#34;: \&amp;#34;ほげ\&amp;#34;, \&amp;#34;emoji\&amp;#34;: \&amp;#34;:thumbsup:\&amp;#34; }&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://developer.rocket.chat/reference/api/rest-api/endpoints/core-endpoints/chat-endpoints/postmessage" target="_blank" rel="noopener"
 &gt;https://developer.rocket.chat/reference/api/rest-api/endpoints/core-endpoints/chat-endpoints/postmessage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/RocketChat/Rocket.Chat/issues/9113" target="_blank" rel="noopener"
 &gt;https://github.com/RocketChat/Rocket.Chat/issues/9113&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] アドレス (id) は変更せずに辞書 (dict) をコピーしたい</title><link>https://blog.ponkotools.com/posts/2022/08/13/python/</link><pubDate>Sat, 13 Aug 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/08/13/python/</guid><description>&lt;p&gt;わかってしまえば当たり前なのですが、ちょっとハマったのでメモ。&lt;/p&gt;
&lt;p&gt;結論から先に言うと、&lt;code&gt;clear()&lt;/code&gt; &lt;code&gt;update()&lt;/code&gt; を使うことで実現できました（ただし排他には要注意）。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Python 3.8.10&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="前提知識"&gt;&lt;a href="#%e5%89%8d%e6%8f%90%e7%9f%a5%e8%ad%98" class="header-anchor"&gt;&lt;/a&gt;前提知識
&lt;/h2&gt;&lt;p&gt;以下の話はググれば解説されているページがいくらでも見つかりますが・・・。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dict&lt;/code&gt; はミュータブルな型なので、代入する場合には注意が必要です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key_a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value_a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key_b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value_b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 値と id の確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;----------&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dict_b&lt;/span&gt; &lt;span class="c1"&gt;# 代入&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 値と id の確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;代入した場合には同じオブジェクトを指すようになるので、以下のように &lt;code&gt;id&lt;/code&gt; が同じになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;dict_a&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;key_a&amp;#39;&lt;/span&gt;: &lt;span class="s1"&gt;&amp;#39;value_a&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;, id:140351608696704
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;dict_b&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;key_b&amp;#39;&lt;/span&gt;: &lt;span class="s1"&gt;&amp;#39;value_b&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;, id:140351608696768
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;dict_a&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;key_b&amp;#39;&lt;/span&gt;: &lt;span class="s1"&gt;&amp;#39;value_b&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;, id:140351608696768
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;dict_b&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;key_b&amp;#39;&lt;/span&gt;: &lt;span class="s1"&gt;&amp;#39;value_b&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;, id:140351608696768
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;なので、&lt;code&gt;dic_a&lt;/code&gt; を変更したら &lt;code&gt;dict_b&lt;/code&gt; の中身も変わります。&lt;/p&gt;
&lt;p&gt;これを回避するには（つまり &lt;code&gt;id&lt;/code&gt; は別で中身だけをコピーしたい場合は） &lt;code&gt;copy()&lt;/code&gt; を使います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_a = {&amp;#34;key_a&amp;#34;: &amp;#34;value_a&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_b = {&amp;#34;key_b&amp;#34;: &amp;#34;value_b&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 値と id の確認
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(f&amp;#39;dict_a={dict_a}, id:{id(dict_a)}&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(f&amp;#39;dict_b={dict_b}, id:{id(dict_b)}&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(f&amp;#39;----------&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_a = dict_b.copy()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 値と id の確認
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(f&amp;#39;dict_a={dict_a}, id:{id(dict_a)}&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(f&amp;#39;dict_b={dict_b}, id:{id(dict_b)}&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この場合は新たにオブジェクトが作成されるので、&lt;code&gt;id&lt;/code&gt; は別で中身は同じになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_a={&amp;#39;key_a&amp;#39;: &amp;#39;value_a&amp;#39;}, id:139764478058368
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_b={&amp;#39;key_b&amp;#39;: &amp;#39;value_b&amp;#39;}, id:139764478058432
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_a={&amp;#39;key_b&amp;#39;: &amp;#39;value_b&amp;#39;}, id:139764476783232
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_b={&amp;#39;key_b&amp;#39;: &amp;#39;value_b&amp;#39;}, id:139764478058432
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="じゃあ-id-を変えずに中身だけをコピーするには"&gt;&lt;a href="#%e3%81%98%e3%82%83%e3%81%82-id-%e3%82%92%e5%a4%89%e3%81%88%e3%81%9a%e3%81%ab%e4%b8%ad%e8%ba%ab%e3%81%a0%e3%81%91%e3%82%92%e3%82%b3%e3%83%94%e3%83%bc%e3%81%99%e3%82%8b%e3%81%ab%e3%81%af" class="header-anchor"&gt;&lt;/a&gt;じゃあ id を変えずに中身だけをコピーするには？
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;clear()&lt;/code&gt; と &lt;code&gt;update()&lt;/code&gt; を使えばできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key_a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value_a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key_b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value_b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 値と id の確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;----------&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 値と id の確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_a={&amp;#39;key_a&amp;#39;: &amp;#39;value_a&amp;#39;}, id:139790269009792
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_b={&amp;#39;key_b&amp;#39;: &amp;#39;value_b&amp;#39;}, id:139790269009856
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_a={&amp;#39;key_b&amp;#39;: &amp;#39;value_b&amp;#39;}, id:139790269009792
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_b={&amp;#39;key_b&amp;#39;: &amp;#39;value_b&amp;#39;}, id:139790269009856
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;dict_a&lt;/code&gt; &lt;code&gt;dict_b&lt;/code&gt; の中身は同じですが、&lt;code&gt;dict_a&lt;/code&gt; の &lt;code&gt;id&lt;/code&gt; は変わっていません。&lt;/p&gt;
&lt;h3 id="関数に引数で渡す場合"&gt;&lt;a href="#%e9%96%a2%e6%95%b0%e3%81%ab%e5%bc%95%e6%95%b0%e3%81%a7%e6%b8%a1%e3%81%99%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;関数に引数で渡す場合
&lt;/h3&gt;&lt;p&gt;Python では全て参照渡しなので、&lt;code&gt;dict&lt;/code&gt; を関数に渡して関数内で変更した場合、その関数の外にも影響を与えます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;target_dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hoge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;piyo&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key_a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value_a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key_b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value_b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 値と id の確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;----------&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;change_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 値と id の確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_a={&amp;#39;key_a&amp;#39;: &amp;#39;value_a&amp;#39;}, id:139844338024320
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_b={&amp;#39;key_b&amp;#39;: &amp;#39;value_b&amp;#39;}, id:139844338024384
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_a={&amp;#39;key_a&amp;#39;: &amp;#39;value_a&amp;#39;, &amp;#39;hoge&amp;#39;: &amp;#39;piyo&amp;#39;}, id:139844338024320
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_b={&amp;#39;key_b&amp;#39;: &amp;#39;value_b&amp;#39;}, id:139844338024384
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="本題"&gt;&lt;a href="#%e6%9c%ac%e9%a1%8c" class="header-anchor"&gt;&lt;/a&gt;本題
&lt;/h2&gt;&lt;p&gt;じゃあ、関数内で &lt;code&gt;dict&lt;/code&gt; を丸ごと差し替えたい場合はどうすればよいか？&lt;br&gt;
引数で渡した値に丸ごと新しい &lt;code&gt;dict&lt;/code&gt; を代入すると、その引数の参照先が変わるだけなので、参照元には反映されません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;target_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hoge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;piyo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key_a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value_a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key_b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value_b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 値と id の確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;----------&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;change_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 値と id の確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_a={&amp;#39;key_a&amp;#39;: &amp;#39;value_a&amp;#39;}, id:139712684732288
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_b={&amp;#39;key_b&amp;#39;: &amp;#39;value_b&amp;#39;}, id:139712684732352
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_a={&amp;#39;key_a&amp;#39;: &amp;#39;value_a&amp;#39;}, id:139712684732288
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_b={&amp;#39;key_b&amp;#39;: &amp;#39;value_b&amp;#39;}, id:139712684732352
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;かと言って、&lt;code&gt;copy()&lt;/code&gt; を使うと新たにオブジェクトが作成されるので、この場合も参照元には反映されません（コピー前のオブジェクトを参照しているため）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;target_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hoge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;piyo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key_a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value_a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key_b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value_b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 値と id の確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;----------&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;change_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 値と id の確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_a={&amp;#39;key_a&amp;#39;: &amp;#39;value_a&amp;#39;}, id:2642357453888
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_b={&amp;#39;key_b&amp;#39;: &amp;#39;value_b&amp;#39;}, id:2642357181760
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_a={&amp;#39;key_a&amp;#39;: &amp;#39;value_a&amp;#39;}, id:2642357453888
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dict_b={&amp;#39;key_b&amp;#39;: &amp;#39;value_b&amp;#39;}, id:2642357181760
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;なので、参照元にも変更を反映したい場合には、前述したように &lt;code&gt;clear()&lt;/code&gt; &lt;code&gt;update()&lt;/code&gt; を使います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;target_dict&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;target_dict&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hoge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;piyo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key_a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value_a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;key_b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value_b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 値と id の確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;----------&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;change_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 値と id の確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dict_b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, id:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;key_a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;value_a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2371211616000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;key_b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;value_b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2371211612864&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;----------&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hoge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;piyo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2371211616000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dict_b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;key_b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;value_b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2371211612864&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="排他には注意"&gt;&lt;a href="#%e6%8e%92%e4%bb%96%e3%81%ab%e3%81%af%e6%b3%a8%e6%84%8f" class="header-anchor"&gt;&lt;/a&gt;排他には注意
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;clear()&lt;/code&gt; &lt;code&gt;update()&lt;/code&gt; という２つの関数を使って &lt;code&gt;dict&lt;/code&gt; を更新するので、並列処理を行っている場合には排他が必要です。&lt;br&gt;
&lt;code&gt;clear()&lt;/code&gt; と &lt;code&gt;update()&lt;/code&gt; の間で値が読み込まれるということが発生しうるからです。&lt;/p&gt;
&lt;p&gt;私の場合、マルチプロセスで動いているアプリで実際にそれが発生しました。&lt;br&gt;
（使っていたのは普通の &lt;code&gt;dict&lt;/code&gt; ではなく &lt;code&gt;multiprocessing.Manager().dict()&lt;/code&gt; ですが）&lt;/p&gt;</description></item><item><title>InfluxDB のコンテナ作成時にデータベースとリテンションポリシーの作成を行う</title><link>https://blog.ponkotools.com/posts/2022/08/09/influxdb/</link><pubDate>Tue, 09 Aug 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/08/09/influxdb/</guid><description>&lt;p&gt;Docker を使って InfluxDB を動かしているのですが、データベースとリテンションポリシーをコンテナ起動時に作成できないかなと思い、調べてみたらやり方を見つけました。&lt;/p&gt;
&lt;p&gt;以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.easydevguide.com/posts/docker_influxdb_init" target="_blank" rel="noopener"
 &gt;https://www.easydevguide.com/posts/docker_influxdb_init&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;InfluxDB: 1.8.10&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="作成方法"&gt;&lt;a href="#%e4%bd%9c%e6%88%90%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;作成方法
&lt;/h2&gt;&lt;p&gt;まず適当な名前（ここでは &lt;code&gt;setup_influxdb.sh&lt;/code&gt;）でシェルスクリプトファイルを作成し、以下のような内容で記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# create database&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;influx -execute &lt;span class="s2"&gt;&amp;#34;CREATE DATABASE dbname&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# create retention policy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;influx -execute &lt;span class="s2"&gt;&amp;#34;CREATE RETENTION POLICY rpname ON dbname DURATION 30d REPLICATION 1 DEFAULT&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;dbname&lt;/code&gt;, &lt;code&gt;rpname&lt;/code&gt;, 保存期間などは適当に置き換えてください。&lt;/p&gt;
&lt;p&gt;これを、InfluxDB のコンテナ内の &lt;code&gt;/docker-entrypoint-initdb.d/&lt;/code&gt; に配置します。&lt;br&gt;
例えば、私の場合は docker-compse を使っているので、以下のようにマウントしました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;influxdb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;influxdb:1.8.10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;influxdb&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;unless-stopped&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;8086&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;influxdb:/var/lib/influxdb&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./setup_influxdb.sh:/docker-entrypoint-initdb.d/setup_influxdb.sh:ro&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;influxdb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでコンテナ起動時にスクリプトが実行され、データベースとリテンションポリシーが作成されます。&lt;/p&gt;
&lt;h2 id="確認方法"&gt;&lt;a href="#%e7%a2%ba%e8%aa%8d%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;確認方法
&lt;/h2&gt;&lt;p&gt;まずコンテナに入ります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker &lt;span class="nb"&gt;exec&lt;/span&gt; -it influxdb bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;データベースの一覧は以下で確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# influx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; show databases
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;リテンションポリシーの一覧は以下で確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# influx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; use dbname
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; show retention policies
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.easydevguide.com/posts/docker_influxdb_init" target="_blank" rel="noopener"
 &gt;https://www.easydevguide.com/posts/docker_influxdb_init&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.magata.net/memo/index.php?InfluxDB%C6%FE%CC%E7" target="_blank" rel="noopener"
 &gt;https://www.magata.net/memo/index.php?InfluxDB%C6%FE%CC%E7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Ubuntu に nginx を入れてリバースプロキシとして使用する</title><link>https://blog.ponkotools.com/posts/2022/08/05/ubuntu-nginx/</link><pubDate>Fri, 05 Aug 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/08/05/ubuntu-nginx/</guid><description>&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="インストール"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;インストール
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install nginx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;http://localhost にアクセスして nginx が起動していることを確認します。&lt;/p&gt;
&lt;h2 id="設定"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;設定
&lt;/h2&gt;&lt;p&gt;nginx の設定ファイルは &lt;code&gt;/etc/nginx/nginx.conf&lt;/code&gt; ですが、この中を見ると、http ディレクティブの中に以下の記述があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;##
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Virtual Host Configs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;##
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;include /etc/nginx/conf.d/*.conf;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;include /etc/nginx/sites-enabled/*;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;conf.d&lt;/code&gt; と &lt;code&gt;sites-enabled&lt;/code&gt; の中に置いた設定ファイルが読み込まれるようになっています。&lt;br&gt;
２つの使い分けについては以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/tomokon/items/e782636c1e5ec6b5dfdc" target="_blank" rel="noopener"
 &gt;https://qiita.com/tomokon/items/e782636c1e5ec6b5dfdc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;というわけで、&lt;code&gt;sites-available&lt;/code&gt; に設定ファイルを作成して、&lt;code&gt;sites-enabled&lt;/code&gt; にシンボリックリンクを作成します。&lt;/p&gt;
&lt;h3 id="conf-ファイルの追加"&gt;&lt;a href="#conf-%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ae%e8%bf%bd%e5%8a%a0" class="header-anchor"&gt;&lt;/a&gt;conf ファイルの追加
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo nano /etc/nginx/sites-available/sample.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;server {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; listen 80 default_server;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; server_name _;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; location / {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_pass http://localhost:5000;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_http_version 1.1;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_set_header Upgrade $http_upgrade;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_set_header Connection keep-alive;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_set_header Host $host;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_cache_bypass $http_upgrade;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; proxy_set_header X-Forwarded-Proto $scheme;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;server_name&lt;/code&gt; の &lt;code&gt;_;&lt;/code&gt; は catch-all の意味らしく、任意の URL に対して有効になります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://nginx.org/en/docs/http/server_names.html" target="_blank" rel="noopener"
 &gt;http://nginx.org/en/docs/http/server_names.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;proxy_pass&lt;/code&gt; が遷移先の URL です。&lt;br&gt;
その他の設定については以下を参考にさせてもらいました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://lh182051.hateblo.jp/entry/2019/11/22/010641" target="_blank" rel="noopener"
 &gt;https://lh182051.hateblo.jp/entry/2019/11/22/010641&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="デフォルトの設定の削除"&gt;&lt;a href="#%e3%83%87%e3%83%95%e3%82%a9%e3%83%ab%e3%83%88%e3%81%ae%e8%a8%ad%e5%ae%9a%e3%81%ae%e5%89%8a%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;デフォルトの設定の削除
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;sites-enabled&lt;/code&gt; の中には最初から &lt;code&gt;default&lt;/code&gt; という設定へのシンボリックリンクがあります。&lt;br&gt;
設定内容次第ではこの default の設定が邪魔になることもあるので、そのような場合は削除しておきます。&lt;/p&gt;
&lt;p&gt;今回の場合は &lt;code&gt;default_server&lt;/code&gt; と &lt;code&gt;server_name _;&lt;/code&gt; が重複しているので、削除しておかないと上手くルーティングできません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo rm /etc/nginx/sites-enabled/default
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="シンボリックリンクの作成"&gt;&lt;a href="#%e3%82%b7%e3%83%b3%e3%83%9c%e3%83%aa%e3%83%83%e3%82%af%e3%83%aa%e3%83%b3%e3%82%af%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;シンボリックリンクの作成
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo ln -s /etc/nginx/sites-available/sample.conf /etc/nginx/sites-enabled/sample
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;nginx を再起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart nginx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以上で完了です。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.microsoft.com/ja-jp/troubleshoot/developer/webapps/aspnetcore/practice-troubleshoot-linux/2-2-install-nginx-configure-it-reverse-proxy" target="_blank" rel="noopener"
 &gt;https://docs.microsoft.com/ja-jp/troubleshoot/developer/webapps/aspnetcore/practice-troubleshoot-linux/2-2-install-nginx-configure-it-reverse-proxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://gist.github.com/kenjiskywalker/4698573" target="_blank" rel="noopener"
 &gt;https://gist.github.com/kenjiskywalker/4698573&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>WSL2 上の Docker コンテナに外部からアクセスする</title><link>https://blog.ponkotools.com/posts/2022/07/29/wsl-docker/</link><pubDate>Fri, 29 Jul 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/07/29/wsl-docker/</guid><description>&lt;p&gt;Ubuntu で Docker を使っている場合はホストとコンテナのポートマッピングさえ行えば外部からアクセスできました。&lt;br&gt;
しかし、WSL2 を使っている場合は Windows と WSL2(Ubuntu) のポートフォワーディングの設定を行わないと外部からはアクセスできません。&lt;/p&gt;
&lt;p&gt;尚、タイトルには「Docker コンテナに外部からアクセス」と書きましたが、Windows と WSL2 の話なので、Docker は関係ありません。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ホスト: Windows 10&lt;/li&gt;
&lt;li&gt;WSL2: Ubuntu 20.04&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="設定方法"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;設定方法
&lt;/h2&gt;&lt;h3 id="wsl2-の-ip-アドレスを調べる"&gt;&lt;a href="#wsl2-%e3%81%ae-ip-%e3%82%a2%e3%83%89%e3%83%ac%e3%82%b9%e3%82%92%e8%aa%bf%e3%81%b9%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;WSL2 の IP アドレスを調べる
&lt;/h3&gt;&lt;p&gt;まずは WSL2 上で以下のコマンドを実行し、eth0 の IP アドレスを調べます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ip addr show dev eth0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;または &lt;code&gt;hostname -I&lt;/code&gt; でも調べられます。&lt;/p&gt;
&lt;h3 id="windows-と-wsl2-のポートフォワーディング設定"&gt;&lt;a href="#windows-%e3%81%a8-wsl2-%e3%81%ae%e3%83%9d%e3%83%bc%e3%83%88%e3%83%95%e3%82%a9%e3%83%af%e3%83%bc%e3%83%87%e3%82%a3%e3%83%b3%e3%82%b0%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Windows と WSL2 のポートフォワーディング設定
&lt;/h3&gt;&lt;p&gt;コマンドプロンプトまたは PowerShell で以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; netsh interface portproxy add v4tov4 &lt;span class="nv"&gt;listenport&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;ポート&amp;gt; &lt;span class="nv"&gt;connectaddress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;WSL2のIPアドレス&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで外部からアクセス可能になります。&lt;br&gt;
設定ができているか確認したい場合は以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; netsh interface portproxy show v4tov4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ipv4 をリッスンする: ipv4 に接続する:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Address Port Address Port
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--------------- ---------- --------------- ----------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="m"&gt;5001&lt;/span&gt; 172.20.93.38 &lt;span class="m"&gt;5001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;設定を削除したい場合は以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; netsh interface portproxy delete v4tov4 &lt;span class="nv"&gt;listenport&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;ポート&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="設定の自動化"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a%e3%81%ae%e8%87%aa%e5%8b%95%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;設定の自動化
&lt;/h2&gt;&lt;p&gt;WSL2 の IP アドレスは起動の度に変わるので、Windows 起動時に自動で設定するようにします。&lt;/p&gt;
&lt;h3 id="windows-上で-wsl2-の-ip-アドレスを取得"&gt;&lt;a href="#windows-%e4%b8%8a%e3%81%a7-wsl2-%e3%81%ae-ip-%e3%82%a2%e3%83%89%e3%83%ac%e3%82%b9%e3%82%92%e5%8f%96%e5%be%97" class="header-anchor"&gt;&lt;/a&gt;Windows 上で WSL2 の IP アドレスを取得
&lt;/h3&gt;&lt;p&gt;PowerShell で以下を実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; &lt;span class="nv"&gt;$IP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; wsl -d Ubuntu-20.04 &lt;span class="nb"&gt;exec&lt;/span&gt; hostname -I
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;しかし、私の環境では複数の IP アドレスが表示されてしまいました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; &lt;span class="nv"&gt;$IP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;172.20.93.38 172.17.0.1 172.18.0.1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;なので、以下のようにスペースで区切って最初の IP アドレスだけを取得できるようにしました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; &lt;span class="nv"&gt;$IP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;wsl -d Ubuntu-20.04 &lt;span class="nb"&gt;exec&lt;/span&gt; hostname -I&lt;span class="o"&gt;)&lt;/span&gt;.split&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34; &amp;#34;&lt;/span&gt;&lt;span class="o"&gt;)[&lt;/span&gt;0&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="スクリプトファイルの作成と実行"&gt;&lt;a href="#%e3%82%b9%e3%82%af%e3%83%aa%e3%83%97%e3%83%88%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ae%e4%bd%9c%e6%88%90%e3%81%a8%e5%ae%9f%e8%a1%8c" class="header-anchor"&gt;&lt;/a&gt;スクリプトファイルの作成と実行
&lt;/h3&gt;&lt;p&gt;以上を踏まえ、以下のようなスクリプトファイルを作成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$IP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;wsl -d Ubuntu-20.04 &lt;span class="nb"&gt;exec&lt;/span&gt; hostname -I&lt;span class="o"&gt;)&lt;/span&gt;.split&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34; &amp;#34;&lt;/span&gt;&lt;span class="o"&gt;)[&lt;/span&gt;0&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;netsh interface portproxy delete v4tov4 &lt;span class="nv"&gt;listenport&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;ポート&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;netsh interface portproxy add v4tov4 &lt;span class="nv"&gt;listenport&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;ポート&amp;gt; &lt;span class="nv"&gt;connectaddress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$IP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとはこれをタスクスケジューラーでログオン時に実行するようにすれば OK です。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/yabeenico/items/15532c703974dc40a7f5" target="_blank" rel="noopener"
 &gt;https://qiita.com/yabeenico/items/15532c703974dc40a7f5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://gunmagisgeek.com/blog/other/7171" target="_blank" rel="noopener"
 &gt;https://gunmagisgeek.com/blog/other/7171&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://scratchpad.jp/ubuntu-on-windows11-13/" target="_blank" rel="noopener"
 &gt;https://scratchpad.jp/ubuntu-on-windows11-13/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>ImageMagick で画像を一括で変換</title><link>https://blog.ponkotools.com/posts/2022/07/27/imagemagick/</link><pubDate>Wed, 27 Jul 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/07/27/imagemagick/</guid><description>&lt;p&gt;Ubuntu で大量の画像ファイルを一括で変換したいときは、ImageMagick のコマンドを使うと便利です。&lt;/p&gt;
&lt;h2 id="インストール"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;インストール
&lt;/h2&gt;&lt;p&gt;私の環境では最初からインストールされていましたが、ない場合は以下でインストールできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install imagemagick
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="画像の変換"&gt;&lt;a href="#%e7%94%bb%e5%83%8f%e3%81%ae%e5%a4%89%e6%8f%9b" class="header-anchor"&gt;&lt;/a&gt;画像の変換
&lt;/h2&gt;&lt;p&gt;例えば、全ての png 画像を jpg に変更したい場合は以下のようにしします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mogrify -format jpg *.png
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;元のファイルは残ったままです。&lt;/p&gt;
&lt;h2 id="リサイズ"&gt;&lt;a href="#%e3%83%aa%e3%82%b5%e3%82%a4%e3%82%ba" class="header-anchor"&gt;&lt;/a&gt;リサイズ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;jpg&lt;/code&gt; ファイルを全てリサイズしたい場合、以下のようにします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mogrify -resize 100x100 *.jpg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ただし、この場合アスペクト比は維持されます。
なので、例えば、640x360 の画像を上記のコマンドでリサイズすると、100x56 のサイズになります。&lt;/p&gt;
&lt;p&gt;アスペクト比を無視して強制的にリサイズしたい場合は &lt;code&gt;!&lt;/code&gt; をつけます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mogrify -resize 100x100! *.jpg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、割合で指定したい場合は以下のようにします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mogrify -resize 50% *.jpg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://analyzegear.co.jp/blog/1561" target="_blank" rel="noopener"
 &gt;https://analyzegear.co.jp/blog/1561&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://liginc.co.jp/394506" target="_blank" rel="noopener"
 &gt;https://liginc.co.jp/394506&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://minoru.okinawa/archives/2995" target="_blank" rel="noopener"
 &gt;https://minoru.okinawa/archives/2995&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Rocket.Chat の読み取りチャンネルで絵文字の追加を許可する</title><link>https://blog.ponkotools.com/posts/2022/07/15/rocketchat/</link><pubDate>Fri, 15 Jul 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/07/15/rocketchat/</guid><description>&lt;p&gt;デフォルトだと読み込み専用チャンネルでは絵文字（リアクション）の追加ができませんが、設定を変更すればできるようになります。&lt;/p&gt;
&lt;p&gt;チャンネルの設定画面で「反応を許可する」を ON にすればいいだけですが、これを設定できるのはデフォルトだと Admin または Owner 権限を持つユーザーのみです。&lt;/p&gt;
&lt;p&gt;他のロールにもこの権限を付与したい場合は、root でログインし、「管理 &amp;gt; 権限」を選択し、「ReadOnly時の反応を設定する」にチェックを入れます。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://martinschoeler.github.io/docs/administrator-guides/permissions/" target="_blank" rel="noopener"
 &gt;https://martinschoeler.github.io/docs/administrator-guides/permissions/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Firefox でブックマーク、検索バー、ロケーションバー（アドレスバー）を新しいタブで開く</title><link>https://blog.ponkotools.com/posts/2022/07/14/firefox/</link><pubDate>Thu, 14 Jul 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/07/14/firefox/</guid><description>&lt;p&gt;よく忘れるのでメモ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ロケーションバー（アドレスバー）に &lt;code&gt;about:config&lt;/code&gt; を入力&lt;/li&gt;
&lt;li&gt;「危険を承知の上で使用する」をクリック&lt;/li&gt;
&lt;li&gt;&lt;code&gt;browser.tabs.loadBookmarksInTabs&lt;/code&gt; で検索して &lt;code&gt;true&lt;/code&gt; に変更
&lt;ul&gt;
&lt;li&gt;ブックマークをクリックしたときに新しいタブで開くようになる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;browser.search.openintab&lt;/code&gt; で検索して &lt;code&gt;true&lt;/code&gt; に変更
&lt;ul&gt;
&lt;li&gt;検索バーでの検索結果が新しいタブに表示されるようになる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;browser.urlbar.openintab&lt;/code&gt; で検索して &lt;code&gt;true&lt;/code&gt; に変更
&lt;ul&gt;
&lt;li&gt;ロケーションバー（アドレスバー）の入力内容が新しいタブで表示されるようになる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://manavinfo.com/lifehack/firefox-setting-newtab/" target="_blank" rel="noopener"
 &gt;https://manavinfo.com/lifehack/firefox-setting-newtab/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://otn.hatenablog.jp/entry/20180520/p1" target="_blank" rel="noopener"
 &gt;https://otn.hatenablog.jp/entry/20180520/p1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Ubuntu にインストールした Rocket.Chat のクライアントソフトが起動しなくなった</title><link>https://blog.ponkotools.com/posts/2022/07/12/ubuntu-rocketchat/</link><pubDate>Tue, 12 Jul 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/07/12/ubuntu-rocketchat/</guid><description>&lt;p&gt;Ubuntu にインストールした Rocket.Chat のデスクトップクライアントアプリが、ある時から急にアプリを起動しても何もウィンドウが表示されなくなってしまいました。&lt;/p&gt;
&lt;p&gt;試しにコマンドラインから起動してみたところ、以下のようなエラーが表示されていました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ rocketchat-desktop 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;node:8749&lt;span class="o"&gt;)&lt;/span&gt; UnhandledPromiseRejectionWarning: SyntaxError: Unexpected end of JSON input
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at JSON.parse &lt;span class="o"&gt;(&lt;/span&gt;&amp;lt;anonymous&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at ElectronStore.Conf._deserialize &lt;span class="o"&gt;(&lt;/span&gt;/opt/Rocket.Chat/resources/app.asar/node_modules/conf/dist/source/index.js:67:43&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at ElectronStore.get store &lt;span class="o"&gt;[&lt;/span&gt;as store&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;/opt/Rocket.Chat/resources/app.asar/node_modules/conf/dist/source/index.js:278:43&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at new Conf &lt;span class="o"&gt;(&lt;/span&gt;/opt/Rocket.Chat/resources/app.asar/node_modules/conf/dist/source/index.js:131:32&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at new ElectronStore &lt;span class="o"&gt;(&lt;/span&gt;/opt/Rocket.Chat/resources/app.asar/node_modules/electron-store/index.js:69:3&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at getElectronStore &lt;span class="o"&gt;(&lt;/span&gt;/opt/Rocket.Chat/resources/app.asar/app/main.js:1311:25&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at getPersistedValues &lt;span class="o"&gt;(&lt;/span&gt;/opt/Rocket.Chat/resources/app.asar/app/main.js:1324:34&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at /opt/Rocket.Chat/resources/app.asar/app/main.js:1363:33
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Generator.next &lt;span class="o"&gt;(&lt;/span&gt;&amp;lt;anonymous&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at /opt/Rocket.Chat/resources/app.asar/node_modules/tslib/tslib.js:117:75
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;Use &lt;span class="sb"&gt;`&lt;/span&gt;rocketchat-desktop --trace-warnings ...&lt;span class="sb"&gt;`&lt;/span&gt; to show where the warning was created&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;node:8749&lt;span class="o"&gt;)&lt;/span&gt; UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async &lt;span class="k"&gt;function&lt;/span&gt; without a catch block, or by rejecting a promise which was not handled with .catch&lt;span class="o"&gt;()&lt;/span&gt;. To terminate the node process on unhandled promise rejection, use the CLI flag &lt;span class="sb"&gt;`&lt;/span&gt;--unhandled-rejections&lt;span class="o"&gt;=&lt;/span&gt;strict&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode&lt;span class="o"&gt;)&lt;/span&gt;. &lt;span class="o"&gt;(&lt;/span&gt;rejection id: 2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;原因はよくわかりませんが、設定ファイルを全削除することで起動するようになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ rm -rf ~/.config/Rocket.Chat
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/RocketChat/Rocket.Chat.Electron/issues/1746" target="_blank" rel="noopener"
 &gt;https://github.com/RocketChat/Rocket.Chat.Electron/issues/1746&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>GitLab CI/CD で Uploading artifacts to coordinator... too large archive のエラーが表示された</title><link>https://blog.ponkotools.com/posts/2022/07/08/gitlab/</link><pubDate>Fri, 08 Jul 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/07/08/gitlab/</guid><description>&lt;p&gt;GitLab CI/CD で成果物をアップロードする際に、サイズが大きすぎるとのエラーが表示されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Uploading&lt;/span&gt; &lt;span class="n"&gt;artifacts&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;coordinator&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;too&lt;/span&gt; &lt;span class="n"&gt;large&lt;/span&gt; &lt;span class="n"&gt;archive&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;XXXX&lt;/span&gt; &lt;span class="n"&gt;responseStatus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;413&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;Entity&lt;/span&gt; &lt;span class="n"&gt;Too&lt;/span&gt; &lt;span class="n"&gt;Large&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;413&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;Entity&lt;/span&gt; &lt;span class="n"&gt;Too&lt;/span&gt; &lt;span class="n"&gt;Large&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;XXXXX&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;FATAL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;too&lt;/span&gt; &lt;span class="n"&gt;large&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Job&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;exit&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="gitlab-の設定"&gt;&lt;a href="#gitlab-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;GitLab の設定
&lt;/h2&gt;&lt;p&gt;まずは GitLab の以下の設定を確認します。&lt;/p&gt;
&lt;p&gt;「Settings &amp;gt; Continuous Integration and Deployment &amp;gt; Maximum artifacts size (MB) 」&lt;/p&gt;
&lt;p&gt;デフォルトでは 100MB に設定されているので、必要ならここを変更します。&lt;/p&gt;
&lt;p&gt;しかし、今回は 7MB 程度のファイルだったので、これが原因ではありませんでした。&lt;/p&gt;
&lt;h2 id="リバースプロキシの設定"&gt;&lt;a href="#%e3%83%aa%e3%83%90%e3%83%bc%e3%82%b9%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;リバースプロキシの設定
&lt;/h2&gt;&lt;p&gt;今回 nginx でリバースプロキシの設定を行っていたのですが、&lt;code&gt;client_max_body_size&lt;/code&gt; の設定を行っていなかったのが原因でした。&lt;br&gt;
&lt;code&gt;client_max_body_size&lt;/code&gt; のデフォルト値は 1MB だそうです。&lt;br&gt;
とりあえず以下のように &lt;code&gt;0&lt;/code&gt; を設定して無制限にしておきました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;server {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; listen 80;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; server_name example.com;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client_max_body_size 0;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://pauledenburg.com/gitlab-ci-upload-artifact-fails-large/" target="_blank" rel="noopener"
 &gt;https://pauledenburg.com/gitlab-ci-upload-artifact-fails-large/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Telegraf が docker.sock にアクセスできない</title><link>https://blog.ponkotools.com/posts/2022/07/02/telegraf/</link><pubDate>Sat, 02 Jul 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/07/02/telegraf/</guid><description>&lt;p&gt;Docker コンテナ内で Telegraf を動かして、Docker の情報を収集するには &lt;code&gt;/var/run/docker.sock&lt;/code&gt; をマウントする必要がありますが、それだけでは以下のように &lt;code&gt;Got permission denied&lt;/code&gt; のエラーが表示されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;E! &lt;span class="o"&gt;[&lt;/span&gt;inputs.docker&lt;span class="o"&gt;]&lt;/span&gt; Error in plugin: Got permission denied &lt;span class="k"&gt;while&lt;/span&gt; trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get &lt;span class="s2"&gt;&amp;#34;http://%2Fvar%2Frun%2Fdocker.sock/v1.24/info&amp;#34;&lt;/span&gt;: dial unix /var/run/docker.sock: connect: permission denied
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;E! &lt;span class="o"&gt;[&lt;/span&gt;inputs.docker&lt;span class="o"&gt;]&lt;/span&gt; Error in plugin: Got permission denied &lt;span class="k"&gt;while&lt;/span&gt; trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get &lt;span class="s2"&gt;&amp;#34;http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json?filters=%7B%22status%22%3A%7B%22running%22%3Atrue%7D%7D&amp;amp;limit=0&amp;#34;&lt;/span&gt;: dial unix /var/run/docker.sock: connect: permission denied
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Telegraf の 1.20.3 以降、Telegraf の実行ユーザーは &lt;code&gt;telegraf&lt;/code&gt; という非 root ユーザーに変わったらしいです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.influxdata.com/blog/docker-run-telegraf-as-non-root/" target="_blank" rel="noopener"
 &gt;https://www.influxdata.com/blog/docker-run-telegraf-as-non-root/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;なので、Telegraf の実行ユーザーが docker コマンドを実行できるように、以下のように &lt;code&gt;user&lt;/code&gt; を指定する必要があるそうです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;telegraf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stat&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%g&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="docker-compose-の場合"&gt;&lt;a href="#docker-compose-%e3%81%ae%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;docker-compose の場合
&lt;/h2&gt;&lt;p&gt;yml 内ではシェル変数を参照できないので、あらかじめ環境変数を設定しておくなど、少し工夫が必要です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;TELEGRAF_UID_GID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;telegraf:&lt;span class="k"&gt;$(&lt;/span&gt;stat -c &lt;span class="s1"&gt;&amp;#39;%g&amp;#39;&lt;/span&gt; /var/run/docker.sock&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt; で環境変数を参照します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${TELEGRAF_UID_GID}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここらへんについては以下の記事が参考になると思います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/06/docker-composeyml-hostname.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/06/docker-composeyml-hostname.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.influxdata.com/blog/docker-run-telegraf-as-non-root/" target="_blank" rel="noopener"
 &gt;https://www.influxdata.com/blog/docker-run-telegraf-as-non-root/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>docker-compose.yml での環境変数の参照とデフォルト値の設定</title><link>https://blog.ponkotools.com/posts/2022/07/01/docker-compose/</link><pubDate>Fri, 01 Jul 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/07/01/docker-compose/</guid><description>&lt;p&gt;公式ドキュメントを見ていろいろ設定方法があることを知ったのでメモです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/compose/compose-file/#interpolation" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/compose/compose-file/#interpolation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下、ほぼ訳しただけです。&lt;/p&gt;
&lt;h2 id="環境変数の参照"&gt;&lt;a href="#%e7%92%b0%e5%a2%83%e5%a4%89%e6%95%b0%e3%81%ae%e5%8f%82%e7%85%a7" class="header-anchor"&gt;&lt;/a&gt;環境変数の参照
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;$VARIABLE&lt;/code&gt; または &lt;code&gt;${VARIABLE}&lt;/code&gt; で参照できます。&lt;br&gt;
もし &lt;code&gt;VARIABLE&lt;/code&gt; が定義されていなければ、空文字に置換されます。&lt;/p&gt;
&lt;h2 id="補間-interpolation"&gt;&lt;a href="#%e8%a3%9c%e9%96%93-interpolation" class="header-anchor"&gt;&lt;/a&gt;補間 (interpolation)
&lt;/h2&gt;&lt;p&gt;以下のようにして、環境変数が設定されていない場合のデフォルト値を指定できます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;${VARIABLE:-default}&lt;/code&gt; とすると、環境変数 &lt;code&gt;VARIABLE&lt;/code&gt; が定義されていないか空の場合に &lt;code&gt;default&lt;/code&gt; に置換されます。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;${VARIABLE-default}&lt;/code&gt; とすると、環境変数 &lt;code&gt;VARIABLE&lt;/code&gt; が定義されていない場合に &lt;code&gt;default&lt;/code&gt; に置換されます。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;同様に、以下のように必須変数を指定できます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;${VARIABLE:?err}&lt;/code&gt; とすると、環境変数 &lt;code&gt;VARIABLE&lt;/code&gt; が定義されていないか空の場合にエラーとなります。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;${VARIABLE?err}&lt;/code&gt; とすると、環境変数 &lt;code&gt;VARIABLE&lt;/code&gt; が定義されていない場合にエラーとなります。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="yaml-のアンカーエイリアス機能"&gt;&lt;a href="#yaml-%e3%81%ae%e3%82%a2%e3%83%b3%e3%82%ab%e3%83%bc%e3%82%a8%e3%82%a4%e3%83%aa%e3%82%a2%e3%82%b9%e6%a9%9f%e8%83%bd" class="header-anchor"&gt;&lt;/a&gt;yaml のアンカー/エイリアス機能
&lt;/h2&gt;&lt;p&gt;以下の記事で初めて知ったのですが、&lt;code&gt;x-&lt;/code&gt; で始まるキーを書くことで、docker-compose で無視されるようになるそうです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://techracho.bpsinc.jp/hachi8833/2020_02_07/87447" target="_blank" rel="noopener"
 &gt;https://techracho.bpsinc.jp/hachi8833/2020_02_07/87447&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/compose/compose-file/#interpolation" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/compose/compose-file/#interpolation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/JhonnyBravo/items/588bf82dcd34c081e326" target="_blank" rel="noopener"
 &gt;https://qiita.com/JhonnyBravo/items/588bf82dcd34c081e326&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://techracho.bpsinc.jp/hachi8833/2020_02_07/87447" target="_blank" rel="noopener"
 &gt;https://techracho.bpsinc.jp/hachi8833/2020_02_07/87447&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>docker-compose.yml で HOSTNAME が参照できない？</title><link>https://blog.ponkotools.com/posts/2022/06/30/docker-compose/</link><pubDate>Thu, 30 Jun 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/06/30/docker-compose/</guid><description>&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt; で &lt;code&gt;$HOSTNAME&lt;/code&gt; と記述すると以下のようなエラーが表示され、かなりはまってしまいました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;The HOSTNAME variable is not set. Defaulting to a blank string
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ubuntu では &lt;code&gt;HOSTNAME&lt;/code&gt; が export されていないそうなので、環境変数として参照できないようです。&lt;br&gt;
どうやらかなり昔からの仕様のようですが、Ubuntu 20.04 でも状況は変わっていません。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://ubuntuforums.org/archive/index.php/t-898924.html" target="_blank" rel="noopener"
 &gt;https://ubuntuforums.org/archive/index.php/t-898924.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;私は誤解していましたが、&lt;code&gt;HOSTNAME&lt;/code&gt; は環境変数ではなくシェル変数です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/blueskyarea/items/7e8bd6efcc538746a569" target="_blank" rel="noopener"
 &gt;https://qiita.com/blueskyarea/items/7e8bd6efcc538746a569&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://www.linux-beginner.com/linux_kihon170.html" target="_blank" rel="noopener"
 &gt;http://www.linux-beginner.com/linux_kihon170.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そして、export されていないから環境変数として yml からは参照できないと。&lt;br&gt;
なので、以下のようにすれば参照できるようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;export&lt;/span&gt; HOSTNAME &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-compose up
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;毎回 export するのが面倒な場合は &lt;code&gt;.bashrc&lt;/code&gt; に書いておくのがいいかもしれません。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://ubuntuforums.org/archive/index.php/t-898924.html" target="_blank" rel="noopener"
 &gt;https://ubuntuforums.org/archive/index.php/t-898924.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/blueskyarea/items/7e8bd6efcc538746a569" target="_blank" rel="noopener"
 &gt;https://qiita.com/blueskyarea/items/7e8bd6efcc538746a569&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://www.linux-beginner.com/linux_kihon170.html" target="_blank" rel="noopener"
 &gt;http://www.linux-beginner.com/linux_kihon170.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] aiohttp で multipart/form-data を使う</title><link>https://blog.ponkotools.com/posts/2022/06/29/python/</link><pubDate>Wed, 29 Jun 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/06/29/python/</guid><description>&lt;p&gt;複数のデータを送るときに使う &lt;code&gt;multipart/form-data&lt;/code&gt; を aiohttp で送る方法です。&lt;/p&gt;
&lt;p&gt;公式ドキュメントは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.aiohttp.org/en/stable/multipart.html" target="_blank" rel="noopener"
 &gt;https://docs.aiohttp.org/en/stable/multipart.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="基本サンプル"&gt;&lt;a href="#%e5%9f%ba%e6%9c%ac%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;基本サンプル
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;aiohttp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;aiohttp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MultipartWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;form-data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;mpwriter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mpwriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hello1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mpwriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hello2&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;aiohttp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClientSession&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;url&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mpwriter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下のような内容で送信されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: multipart/form-data; boundary=69ae25abec5c4a038dc2deb4a0952eb3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--69ae25abec5c4a038dc2deb4a0952eb3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: text/plain; charset=utf-8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Length: 6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--69ae25abec5c4a038dc2deb4a0952eb3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: text/plain; charset=utf-8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Length: 6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hello2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--69ae25abec5c4a038dc2deb4a0952eb3--
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="テキストデータ"&gt;&lt;a href="#%e3%83%86%e3%82%ad%e3%82%b9%e3%83%88%e3%83%87%e3%83%bc%e3%82%bf" class="header-anchor"&gt;&lt;/a&gt;テキストデータ
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;mpwriter.append&lt;/code&gt; にテキストを渡した場合、デフォルトでは &lt;code&gt;Content-Type&lt;/code&gt; は &lt;code&gt;text/plain&lt;/code&gt; になるそうです。&lt;/p&gt;
&lt;h3 id="バイナリデータ"&gt;&lt;a href="#%e3%83%90%e3%82%a4%e3%83%8a%e3%83%aa%e3%83%87%e3%83%bc%e3%82%bf" class="header-anchor"&gt;&lt;/a&gt;バイナリデータ
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;mpwriter.append&lt;/code&gt; にバイナリデータを渡した場合、デフォルトでは &lt;code&gt;Content-Type&lt;/code&gt; は &lt;code&gt;application/octet-stream&lt;/code&gt; になるそうです。&lt;br&gt;
変更したい場合は以下のように第２引数で指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mpwriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;image/jpeg&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、&lt;code&gt;name&lt;/code&gt; や &lt;code&gt;filename&lt;/code&gt; などを指定したい場合は、&lt;code&gt;set_content_disposition&lt;/code&gt; を使用するようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mpwriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;image/jpeg&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_content_disposition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;form-data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;filename&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="json-を送りたい場合"&gt;&lt;a href="#json-%e3%82%92%e9%80%81%e3%82%8a%e3%81%9f%e3%81%84%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;JSON を送りたい場合
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;append_json&lt;/code&gt; に dict 型のデータを渡せばOKです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mpwriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append_json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;test&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;passed&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="json-と画像を一緒に送る例"&gt;&lt;a href="#json-%e3%81%a8%e7%94%bb%e5%83%8f%e3%82%92%e4%b8%80%e7%b7%92%e3%81%ab%e9%80%81%e3%82%8b%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;JSON と画像を一緒に送る例
&lt;/h2&gt;&lt;p&gt;以前、requests モジュールを使って &lt;code&gt;multipart/form-data&lt;/code&gt; のデータを送る記事を書きました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/06/webapi-multipartform-data.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/06/webapi-multipartform-data.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これを aiohttp で書いてみたのが以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;aiohttp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;aiohttp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MultipartWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;form-data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;mpwriter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;camera_id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hoge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;piyo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="c1"&gt;# 各カメラのID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 適当なテキストデータ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;json_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;camera_id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;camera_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;datetime&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 適当な画像ファイルを読み込む&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;send_image.jpg&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rb&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# JSON の追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mpwriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_content_disposition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;form-data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;camera_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 画像の追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mpwriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;image/jpeg&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_content_disposition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;form-data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;camera_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;camera_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 送信&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;aiohttp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClientSession&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://localhost:8000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mpwriter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.aiohttp.org/en/stable/multipart.html" target="_blank" rel="noopener"
 &gt;https://docs.aiohttp.org/en/stable/multipart.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] flask で async/await を使う</title><link>https://blog.ponkotools.com/posts/2022/06/28/python-flask/</link><pubDate>Tue, 28 Jun 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/06/28/python-flask/</guid><description>&lt;p&gt;&lt;code&gt;flask[async]&lt;/code&gt; のインストールすれば、普通に async/await の構文が使えました。&lt;/p&gt;
&lt;p&gt;公式ドキュメントは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://flask.palletsprojects.com/en/2.1.x/async-await/" target="_blank" rel="noopener"
 &gt;https://flask.palletsprojects.com/en/2.1.x/async-await/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;Python 3.8.10&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="インストール"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;インストール
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pip install flask&lt;span class="o"&gt;[&lt;/span&gt;async&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/test&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;GET&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;elapsed time&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;0.0.0.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://flask.palletsprojects.com/en/2.1.x/async-await/" target="_blank" rel="noopener"
 &gt;https://flask.palletsprojects.com/en/2.1.x/async-await/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Portainer API を使って Docker Engine API を叩いてみる</title><link>https://blog.ponkotools.com/posts/2022/06/27/portainer/</link><pubDate>Mon, 27 Jun 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/06/27/portainer/</guid><description>&lt;p&gt;Docker を WebUI で操作できる Portainer には API が用意されており、これを使えば Portainer の UI でできることを全て自動化できます。また、Portainer API を介して Docker Engine API も叩くことができるので試してみました。&lt;/p&gt;
&lt;p&gt;Portainer の API のドキュメントは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.portainer.io/api/docs" target="_blank" rel="noopener"
 &gt;https://docs.portainer.io/api/docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Docker Engine API のドキュメントは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/engine/api/v1.41/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/engine/api/v1.41/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Python + aiohttp で実装してみました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Docker 20.10.12&lt;/li&gt;
&lt;li&gt;Portainer 2.13.1&lt;/li&gt;
&lt;li&gt;Python 3.8.10&lt;/li&gt;
&lt;li&gt;aiohttp 3.8.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;p&gt;細かい解説は後にして、先にコード全体を載せます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;aiohttp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;PORTAINER_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://portainer_url&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;aiohttp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClientSession&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# トークンを取得&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PORTAINER_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;/api/auth&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Username&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Admin&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Password&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;AdminPassword&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;jwt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ヘッダー&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Authorization&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#headers={ &amp;#39;X-API-Key&amp;#39;: &amp;#39;token&amp;#39; }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# EnvironmentID を取得&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PORTAINER_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;/api/endpoint_groups&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;environments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;environments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# コンテナ一覧の取得&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PORTAINER_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;/api/endpoints/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;/docker/containers/json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;all&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;true&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;containers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="トークンの取得"&gt;&lt;a href="#%e3%83%88%e3%83%bc%e3%82%af%e3%83%b3%e3%81%ae%e5%8f%96%e5%be%97" class="header-anchor"&gt;&lt;/a&gt;トークンの取得
&lt;/h3&gt;&lt;p&gt;Portainer のアカウントを使って JWT トークンを取得します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PORTAINER_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;/api/auth&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Username&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Admin&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Password&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;AdminPassword&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;jwt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このトークンは8時間の間だけ有効だそうです。&lt;br&gt;
または、Portainer の myaccount 画面からでも API トークンを発行できます。&lt;br&gt;
それぞれヘッダーの書き方が少し異なります。&lt;/p&gt;
&lt;p&gt;前者の場合は&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Authorization&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;後者の場合は&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;X-API-Key&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;token&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;のように記述します。&lt;/p&gt;
&lt;h3 id="environmentendpoint-id-の取得"&gt;&lt;a href="#environmentendpoint-id-%e3%81%ae%e5%8f%96%e5%be%97" class="header-anchor"&gt;&lt;/a&gt;Environment(endpoint) ID の取得
&lt;/h3&gt;&lt;p&gt;Portainer は複数の Docker ホストを管理できるので、Docker Engine API を叩く際にはどのホストの Docker に対する操作かを指定する必要があります。　　　　
なので、Docker Engine API を叩く前に Environment の一覧を取得します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://app.swaggerhub.com/apis/portainer/portainer-ce/2.13.1#/endpoint_groups/EndpointGroupList" target="_blank" rel="noopener"
 &gt;https://app.swaggerhub.com/apis/portainer/portainer-ce/2.13.1#/endpoint_groups/EndpointGroupList&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PORTAINER_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;/api/endpoint_groups&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;environments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;environments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="コンテナの一覧を取得"&gt;&lt;a href="#%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e3%81%ae%e4%b8%80%e8%a6%a7%e3%82%92%e5%8f%96%e5%be%97" class="header-anchor"&gt;&lt;/a&gt;コンテナの一覧を取得
&lt;/h3&gt;&lt;p&gt;コンテナの一覧を取得してみます。&lt;br&gt;
API の仕様は以下を参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/engine/api/v1.41/#tag/Container" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/engine/api/v1.41/#tag/Container&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Portainer のエンドポイント &lt;code&gt;/api/endpoints/{id}/docker&lt;/code&gt; より後ろが docker のエンドポイントと同じになるみたいですね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PORTAINER_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;/api/endpoints/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;/docker/containers/json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;all&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;true&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;containers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここまでやれば、後は大体のことができるんじゃないかと思います。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.portainer.io/api/docs" target="_blank" rel="noopener"
 &gt;https://docs.portainer.io/api/docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/engine/api/v1.41/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/engine/api/v1.41/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>リバースプロキシの背後で Grafana を動かす</title><link>https://blog.ponkotools.com/posts/2022/06/24/grafana/</link><pubDate>Fri, 24 Jun 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/06/24/grafana/</guid><description>&lt;p&gt;サーバー側だけでなく Grafana 側の設定も行う必要があったのでメモです。&lt;/p&gt;
&lt;p&gt;一応公式ドキュメントに方法が載っています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/tutorials/run-grafana-behind-a-proxy/" target="_blank" rel="noopener"
 &gt;https://grafana.com/tutorials/run-grafana-behind-a-proxy/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回はサブディレクトリで設定したかったのと、Grafana を docker-compose で動かしていたので、&lt;code&gt;docker-compose.yml&lt;/code&gt; の環境変数で以下のように設定しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;GF_SERVER_ROOT_URL=%(protocol)s://%(domain)s:%(http_port)s/grafana/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;GF_SERVER_SERVE_FROM_SUB_PATH=true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;サーバー側の設定は普通にリバースプロキシの設定を行うだけなので省略します。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/tutorials/run-grafana-behind-a-proxy/" target="_blank" rel="noopener"
 &gt;https://grafana.com/tutorials/run-grafana-behind-a-proxy/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/ryotaro76/items/22fa5e877eaab8b567e1" target="_blank" rel="noopener"
 &gt;https://qiita.com/ryotaro76/items/22fa5e877eaab8b567e1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] ログドライバーでログの出力先を syslog に設定する</title><link>https://blog.ponkotools.com/posts/2022/06/23/docker/</link><pubDate>Thu, 23 Jun 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/06/23/docker/</guid><description>&lt;p&gt;Docker コンテナで標準出力されているログを syslog に記録するようにログドライバーを設定します。&lt;/p&gt;
&lt;p&gt;Docker のログドライバーで設定できるものには他にもいろいろあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://matsuand.github.io/docs.docker.jp.onthefly/config/containers/logging/configure/" target="_blank" rel="noopener"
 &gt;https://matsuand.github.io/docs.docker.jp.onthefly/config/containers/logging/configure/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;オプションはログドライバーによって異なるようで、syslog の場合は以下になります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://matsuand.github.io/docs.docker.jp.onthefly/config/containers/logging/syslog/" target="_blank" rel="noopener"
 &gt;https://matsuand.github.io/docs.docker.jp.onthefly/config/containers/logging/syslog/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上を踏まえ、docker-compose でログドライバーを設定する例が以下になります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;syslog&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;my-app-name&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;デフォルトでは &lt;code&gt;appname&lt;/code&gt; がコンテナIDになって分かりづらいので、&lt;code&gt;tag&lt;/code&gt; で設定しています。&lt;/p&gt;
&lt;h2 id="余談"&gt;&lt;a href="#%e4%bd%99%e8%ab%87" class="header-anchor"&gt;&lt;/a&gt;余談
&lt;/h2&gt;&lt;p&gt;コンテナ内で動かしている Python のアプリケーションでは、もともと logging モジュールで syslog に記録するよう設定していました。&lt;br&gt;
これを標準出力にし、Docker のログドライバーで設定できるようにすれば、コンテナを使う側が出力先を決められて便利かなと思いました。&lt;/p&gt;
&lt;p&gt;しかし、Python 側では5段階に分けられていたログレベルが、標準出力を介すことで、Info (stdout) と Error (stderr) の2レベルに平坦化されてしまうことが分かり、結局 Python 側で syslog に記録するようにしました。&lt;/p&gt;
&lt;p&gt;もしかしたから何か上手いやり方があるのかもしれませんが・・・。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/Esfahan/items/5e5a9ae7882bb0eaaf5f" target="_blank" rel="noopener"
 &gt;https://qiita.com/Esfahan/items/5e5a9ae7882bb0eaaf5f&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] OpenCV + python のマルチステージビルドを行う</title><link>https://blog.ponkotools.com/posts/2022/06/20/docker/</link><pubDate>Mon, 20 Jun 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/06/20/docker/</guid><description>&lt;p&gt;Python の OpenCV で GStreamer を使う場合、自前でビルドする必要があり、そのための Dockerfile を以前作成しました。&lt;/p&gt;
&lt;p&gt;その時の記事が以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/11/opencv-gstreamer.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2021/11/opencv-gstreamer.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ただ、これで作成した Docker イメージのサイズが 2.5GB くらいあり、もっとサイズを小さくできないかなと考えていました。&lt;/p&gt;
&lt;p&gt;その過程でマルチステージビルドというものを知ったのですが、OpenCV のビルドの成果物をどうやって最後のステージに持ってきたらよいか分からず悩んでいたら、以下のページを見つけました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/NVIDIA/nvidia-docker/issues/806" target="_blank" rel="noopener"
 &gt;https://github.com/NVIDIA/nvidia-docker/issues/806&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/NVIDIA/gpu-rest-engine/blob/master/Dockerfile.caffe_server#L26-L41" target="_blank" rel="noopener"
 &gt;https://github.com/NVIDIA/gpu-rest-engine/blob/master/Dockerfile.caffe_server#L26-L41&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/63592138/opencv-docker-multistage-build-cannot-install-prebuilt-source" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/63592138/opencv-docker-multistage-build-cannot-install-prebuilt-source&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ビルドステージでは、&lt;code&gt;make install&lt;/code&gt; の後、&lt;code&gt;ldconfig&lt;/code&gt; で共有リンクを作成しています。&lt;br&gt;
リリースステージでは &lt;code&gt;/usr/local/lib&lt;/code&gt; 以下を全てコピーし、&lt;code&gt;ldconfig&lt;/code&gt; で共有リンクを作成しています。&lt;/p&gt;
&lt;p&gt;というわけで、これを参考にマルチステージビルドを行ってみました。
ただ、私の場合、&lt;code&gt;/usr/local/lib&lt;/code&gt; のコピーだけでは依存パッケージが不足していて動かなかったので、&lt;code&gt;/usr/lib&lt;/code&gt; と &lt;code&gt;/usr/share&lt;/code&gt; の中身も全部コピーしたら動くようになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;COPY --from=build /usr/lib /usr/lib
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;COPY --from=build /usr/share /usr/share
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;COPY --from=build /usr/local/lib /usr/local/lib
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RUN ldconfig
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以上で、イメージサイズを 1.9GB まで減らせました。&lt;br&gt;
ここらへん、本当に依存しているパッケージだけをコピーするようにできれば、まだまだサイズを小さくできそうではあります。&lt;/p&gt;
&lt;p&gt;以下、Dockerfile のサンプルです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Stage1: build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ubuntu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;20.04&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# tzdataのタイムゾーン入力を求められないようにする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://tmyoda.hatenablog.com/entry/20210124/1611416396&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ENV&lt;/span&gt; &lt;span class="n"&gt;TZ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Asia&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Tokyo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;ln&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;snf&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;share&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;zoneinfo&lt;/span&gt;&lt;span class="o"&gt;/$&lt;/span&gt;&lt;span class="n"&gt;TZ&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;localtime&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;TZ&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;recommends&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;software&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;common&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ca&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;certificates&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 必要なパッケージをインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libgl1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mesa&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libsm6&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;git&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;wget&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;unzip&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# OpenCV: Required build dependencies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# https://docs.opencv.org/4.x/d2/de6/tutorial_py_setup_in_ubuntu.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cmake&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;numpy&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libavcodec&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libavformat&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libswscale&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libgtk2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libgtk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# OpenCV: Optional Dependencies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libpng&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libjpeg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libopenexr&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libtiff&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libwebp&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# OpenCV のビルド時に -D WITH_QT=ON を設定するために以下が必要だった&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;qtbase5&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;qtdeclarative5&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# gstreamer のインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# https://gstreamer.freedesktop.org/documentation/installing/on-linux.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libgstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libgstreamer&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;base1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libgstreamer&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bad1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;good&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bad&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ugly&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;libav&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;alsa&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;gl&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;gtk3&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;qt5&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pulseaudio&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# aptのクリア&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;autoremove&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rf&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lists&lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# OpenCV のビルドとインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://docs.opencv.org/master/d2/de6/tutorial_py_setup_in_ubuntu.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://toriten1024.hatenablog.com/entry/2018/09/29/012205&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://dlrecord.hatenablog.com/entry/2017/12/15/145356&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://atmarkit.itmedia.co.jp/ait/articles/1704/10/news134.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;mkdir&lt;/span&gt; &lt;span class="n"&gt;opencv&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# OpenCV のダウンロード&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;wget&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;archive&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;certificate&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;unzip&lt;/span&gt; &lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# OpenCV の cmake&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mkdir&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cmake&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;CMAKE_BUILD_TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;RELEASE&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;BUILD_DOCS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OFF&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;BUILD_EXAMPLES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OFF&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;BUILD_TESTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OFF&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;WITH_1394&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OFF&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;WITH_GSTREAMER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ON&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;WITH_FFMPEG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ON&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# cv2.waitKey() を使うためには WITH_QT=ON にする必要があった&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;WITH_QT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ON&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# OpenCV のビルド ※ $(nproc) はコア数を返す、make を並列処理させて高速化したい場合は指定する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#make -j${nproc} &amp;amp;&amp;amp; \&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#make -j2 &amp;amp;&amp;amp; \&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ldconfig&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 後始末&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rf&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Stage2: release&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ubuntu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;20.04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# tzdataのタイムゾーン入力を求められないようにする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://tmyoda.hatenablog.com/entry/20210124/1611416396&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ENV&lt;/span&gt; &lt;span class="n"&gt;TZ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Asia&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Tokyo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;ln&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;snf&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;share&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;zoneinfo&lt;/span&gt;&lt;span class="o"&gt;/$&lt;/span&gt;&lt;span class="n"&gt;TZ&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;localtime&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;TZ&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 必要なパッケージをインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;recommends&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;numpy&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# aptのクリア&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;autoremove&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rf&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lists&lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Copy binary and dependencies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;COPY&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;COPY&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;share&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;share&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;COPY&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;ldconfig&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 必要なプラグインをインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;pip3&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;aiohttp&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rich&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ruamel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yaml&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pymongo&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;3.12&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;influxdb&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;flask&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cors&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pytest&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mock&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mongomock&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;websockets&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;trusted&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="n"&gt;pypi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;trusted&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pythonhosted&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# bash起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/bin/bash&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/NVIDIA/nvidia-docker/issues/806" target="_blank" rel="noopener"
 &gt;https://github.com/NVIDIA/nvidia-docker/issues/806&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/NVIDIA/gpu-rest-engine/blob/master/Dockerfile.caffe_server#L26-L41" target="_blank" rel="noopener"
 &gt;https://github.com/NVIDIA/gpu-rest-engine/blob/master/Dockerfile.caffe_server#L26-L41&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/63592138/opencv-docker-multistage-build-cannot-install-prebuilt-source" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/63592138/opencv-docker-multistage-build-cannot-install-prebuilt-source&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] コンテナ内からホストにアクセスする</title><link>https://blog.ponkotools.com/posts/2022/06/17/docker/</link><pubDate>Fri, 17 Jun 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/06/17/docker/</guid><description>&lt;p&gt;コンテナ内では &lt;code&gt;localhost&lt;/code&gt; はコンテナ自身を指すので使えません。&lt;br&gt;
かといってホストの IP アドレスを直接参照すると、IP アドレスが変わったときに困ります。&lt;/p&gt;
&lt;p&gt;このような場合、&lt;code&gt;host.docker.internal&lt;/code&gt; を使います。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;host.docker.internal&lt;/code&gt; はもともと Windows と Mac でしか使えなかったようですが、Docker 20.10 からLinux でも使えるようになったそうです。&lt;br&gt;
この機能を有効化するには &lt;code&gt;--add-host&lt;/code&gt; で &lt;code&gt;host.docker.internal:host-gateway&lt;/code&gt; を指定する必要があるようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run -it --rm &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --add-host&lt;span class="o"&gt;=&lt;/span&gt;host.docker.internal:host-gateway &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image_name
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;docker-compose の場合は &lt;code&gt;extra_hosts&lt;/code&gt; で指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;extra_hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;host.docker.internal:host-gateway&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/skobaken/items/03a8b9d0e443745862ac" target="_blank" rel="noopener"
 &gt;https://qiita.com/skobaken/items/03a8b9d0e443745862ac&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://medium.com/@TimvanBaarsen/how-to-connect-to-the-docker-host-from-inside-a-docker-container-112b4c71bc66" target="_blank" rel="noopener"
 &gt;https://medium.com/@TimvanBaarsen/how-to-connect-to-the-docker-host-from-inside-a-docker-container-112b4c71bc66&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://uepon.hatenadiary.com/entry/2021/06/02/002613" target="_blank" rel="noopener"
 &gt;https://uepon.hatenadiary.com/entry/2021/06/02/002613&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://dora.bk.tsukuba.ac.jp/~takeuchi/?%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%2Fdocker%2F%E8%A6%9A%E6%9B%B8" target="_blank" rel="noopener"
 &gt;https://dora.bk.tsukuba.ac.jp/~takeuchi/?%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%2Fdocker%2F%E8%A6%9A%E6%9B%B8&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] コンテナ内からホストにアクセスする</title><link>https://blog.ponkotools.com/posts/2022/06/16/docker-traefik/</link><pubDate>Thu, 16 Jun 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/06/16/docker-traefik/</guid><description>&lt;p&gt;ググってもなかなかサンプルが見当たらずかなりはまりました。&lt;/p&gt;
&lt;p&gt;最終的には以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/shiitake256/items/a9cd1f525fd97c224f52" target="_blank" rel="noopener"
 &gt;https://qiita.com/shiitake256/items/a9cd1f525fd97c224f52&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Docker + Traefik の基本的な設定は以前の記事をご覧ください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/06/docker-traefik.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/06/docker-traefik.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Docker 20.10.12&lt;/li&gt;
&lt;li&gt;Traefik v2.7&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="イメージ図"&gt;&lt;a href="#%e3%82%a4%e3%83%a1%e3%83%bc%e3%82%b8%e5%9b%b3" class="header-anchor"&gt;&lt;/a&gt;イメージ図
&lt;/h2&gt;&lt;p&gt;やりたいことは以下のような感じです。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="1007px" data-flex-grow="419" height="121" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/06/16/docker-traefik/image.png" width="508"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;ホストのURL&amp;gt;/api1/&lt;/code&gt; へのアクセスはポート3000へ&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;ホストのURL&amp;gt;/api2/&lt;/code&gt; へのアクセスはポート4000へ&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプル"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;サンプル
&lt;/h2&gt;&lt;p&gt;簡単な解説をコメントに書いています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;3000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;4000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.enable=true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;#------------------------------&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# foo という名前のルーターを定義し、エントリーポイント http と関連付け&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.foo.entrypoints=http&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# リクエストパス /api1 とマッチするよう指定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.foo.rule=PathPrefix(`/api1{regex:$$|/.*}`)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# foo-middleware という名前のミドルウェアを定義し、ルーター foo と関連付け&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.foo.middlewares=foo-middleware&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# サービスにリクエストを行う前にリクエストパスの先頭の /api1 を取り除くように指定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.middlewares.foo-middleware.stripprefix.prefixes=/api1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# foo-service という名前のサービスを定義し、ルーター foo と関連付け&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.foo.service=foo-service&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# foo-service へのアクセスをポート3000 へ飛ばす&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.services.foo-service.loadbalancer.server.port=3000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;#------------------------------&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.bar.entrypoints=http&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.bar.rule=PathPrefix(`/api2{regex:$$|/.*}`)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.bar.middlewares=bar-middleware&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.middlewares.bar-middleware.stripprefix.prefixes=/api2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.bar.service=bar-service&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.services.bar-service.loadbalancer.server.port=4000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;ports&lt;/code&gt; でホストのポートとマッピングしていますが、実際には &lt;code&gt;expose&lt;/code&gt; でコンテナ側のポートを開けるだけのほうがよいと思います。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/shiitake256/items/a9cd1f525fd97c224f52" target="_blank" rel="noopener"
 &gt;https://qiita.com/shiitake256/items/a9cd1f525fd97c224f52&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://community.traefik.io/t/docker-container-with-multiple-ports/4657/2" target="_blank" rel="noopener"
 &gt;https://community.traefik.io/t/docker-container-with-multiple-ports/4657/2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Docker + Traefik で複数のポートを公開しているコンテナのルーティングを行う</title><link>https://blog.ponkotools.com/posts/2022/06/15/docker-traefik/</link><pubDate>Wed, 15 Jun 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/06/15/docker-traefik/</guid><description>&lt;p&gt;ググってもなかなかサンプルが見当たらずかなりはまりました。&lt;/p&gt;
&lt;p&gt;最終的には以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://community.traefik.io/t/docker-container-with-multiple-ports/4657/2" target="_blank" rel="noopener"
 &gt;https://community.traefik.io/t/docker-container-with-multiple-ports/4657/2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Docker + Traefik の基本的な設定は以前の記事をご覧ください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/06/docker-traefik.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/06/docker-traefik.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Docker 20.10.12&lt;/li&gt;
&lt;li&gt;Traefik v2.7&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="イメージ図"&gt;&lt;a href="#%e3%82%a4%e3%83%a1%e3%83%bc%e3%82%b8%e5%9b%b3" class="header-anchor"&gt;&lt;/a&gt;イメージ図
&lt;/h2&gt;&lt;p&gt;やりたいことは以下のような感じです。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="1007px" data-flex-grow="419" height="121" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/06/15/docker-traefik/image.png" width="508"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;api1.localhost&lt;/code&gt; へのアクセスはポート3000へ&lt;/li&gt;
&lt;li&gt;&lt;code&gt;api2.localhost&lt;/code&gt; へのアクセスはポート4000へ&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプル"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;サンプル
&lt;/h2&gt;&lt;p&gt;簡単な解説をコメントに書いています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;3000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;4000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.enable=true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;#------------------------------&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# foo という名前のルーターを定義し、&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# エントリーポイント http (traefik側で設定した任意の名前) と関連付け&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.foo.entrypoints=http&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ルーター foo のホスト名を &amp;#34;api1.localhost&amp;#34; に設定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.foo.rule=Host(`api1.localhost`)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# foo-service という名前のサービスを定義し、ルーター foo と関連付け&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.foo.service=foo-service&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# foo-service へのアクセスをポート3000 へ飛ばす&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.services.foo-service.loadbalancer.server.port=3000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;#------------------------------&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.bar.entrypoints=http&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.bar.rule=Host(`api2.localhost`)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.bar.service=bar-service&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.services.bar-service.loadbalancer.server.port=4000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;ports&lt;/code&gt; でホストのポートとマッピングしていますが、実際には &lt;code&gt;expose&lt;/code&gt; でコンテナ側のポートを開けるだけのほうがよいと思います。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://community.traefik.io/t/docker-container-with-multiple-ports/4657/2" target="_blank" rel="noopener"
 &gt;https://community.traefik.io/t/docker-container-with-multiple-ports/4657/2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/shiitake256/items/a9cd1f525fd97c224f52" target="_blank" rel="noopener"
 &gt;https://qiita.com/shiitake256/items/a9cd1f525fd97c224f52&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Docker + Traefik でリバースプロキシサーバーを立てる</title><link>https://blog.ponkotools.com/posts/2022/06/14/docker-traefik/</link><pubDate>Tue, 14 Jun 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/06/14/docker-traefik/</guid><description>&lt;p&gt;最初 nginx でリバースプロキシサーバーを構築していたのですが、いろいろ調べていく中で Traefik というサーバーの存在を知りました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.traefik.io/traefik/" target="_blank" rel="noopener"
 &gt;https://doc.traefik.io/traefik/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;公式ではエッジルーターという言い方がされていますが、要はリバースプロキシ＋ロードバランサーという感じらしいです。&lt;br&gt;
nginx より後発で、Docker との親和性が高いとのことで試しに使ってみました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Docker: 20.10.12&lt;/li&gt;
&lt;li&gt;Traefik: v2.7&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Traefik 自身も Docker で動かします。&lt;/p&gt;
&lt;h2 id="docker-network-の作成"&gt;&lt;a href="#docker-network-%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;docker network の作成
&lt;/h2&gt;&lt;p&gt;アプリと Traefik で共通で使用するネットワークを作成しておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker network create sample-network
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="traefik-の設定"&gt;&lt;a href="#traefik-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Traefik の設定
&lt;/h2&gt;&lt;p&gt;Traefik の設定は &lt;code&gt;/etc/traefik/traefik.yml&lt;/code&gt; に記述する方法と、&lt;code&gt;docker-compose.yml&lt;/code&gt; で指定する方法があるようです。&lt;br&gt;
前者の例が多いですが、後者の方が &lt;code&gt;docker-compose.yml&lt;/code&gt; 一つで設定が完結して良いと思うのは私だけでしょうか？&lt;/p&gt;
&lt;h3 id="設定ファイルに記述する例"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ab%e8%a8%98%e8%bf%b0%e3%81%99%e3%82%8b%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;設定ファイルに記述する例
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;traefik.yml&lt;/code&gt; というファイルを作成して、以下のように記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Providers config&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Docker との連携を有効にする&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;docker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# false に指定することで Label 付けしていない docker コンテナを Traefik が無視するようになる&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;exposedByDefault&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 使用するネットワーク&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;sample-network&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;entryPoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# http という任意の名前のエントリーポイントを定義し、80番ポートをリッスンするよう指定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;:80&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;:443&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# API/Dashboard config&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# WebUI にアクセスできるように設定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;insecure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Trafik を起動します。&lt;br&gt;
ネットには docker-compose を使った例が多いですが、とりあえず &lt;code&gt;docker run&lt;/code&gt; で動かしてみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run -it --rm &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --name reverse-proxy &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --network sample-network &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /var/run/docker.sock:/var/run/docker.sock &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v &lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;/traefik.yml:/etc/traefik/traefik.yml &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -p 80:80 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -p 8080:8080 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; traefik:v2.7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とりあえずこれで、http://localhost:8080 にアクセスすると Traefik の WebUI が表示されるかと思います。&lt;/p&gt;
&lt;h3 id="docker-composeyml-で設定する例"&gt;&lt;a href="#docker-composeyml-%e3%81%a7%e8%a8%ad%e5%ae%9a%e3%81%99%e3%82%8b%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;docker-compose.yml で設定する例
&lt;/h3&gt;&lt;p&gt;上記の設定を &lt;code&gt;docker-compose.yml&lt;/code&gt; のみで行った場合の例です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;3.9&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;reverse-proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;traefik:v2.7&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ファイルで設定する場合は以下&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;#- type: bind&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# source: ./traefik.yml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# target: /etc/traefik/traefik.yml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sample-network&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# traefik.yml の代わりに command で設定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- --&lt;span class="l"&gt;providers.docker.exposedByDefault=false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- --&lt;span class="l"&gt;providers.docker.network=sample-network&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- --&lt;span class="l"&gt;entryPoints.http.address=:80&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- --&lt;span class="l"&gt;entryPoints.https.address=:443&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- --&lt;span class="l"&gt;api.insecure=true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;sample-network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="アプリケーション側の設定"&gt;&lt;a href="#%e3%82%a2%e3%83%97%e3%83%aa%e3%82%b1%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3%e5%81%b4%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;アプリケーション側の設定
&lt;/h2&gt;&lt;p&gt;ルーティングの設定などは全てコンテナのラベルで設定します。
他のサーバーだとサーバー側の設定を変更する必要がありますが、 Traefik+Docker だとコンテナの増減に対して対応しやすいなと思いました。&lt;/p&gt;
&lt;p&gt;とりあえず &lt;code&gt;docker run&lt;/code&gt; で動かしてみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -it --rm &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --network sample-network &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -l &lt;span class="s2"&gt;&amp;#34;traefik.enable=true&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -l &lt;span class="s2"&gt;&amp;#34;traefik.http.routers.api.entrypoints=http&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -l &lt;span class="s2"&gt;&amp;#34;traefik.http.routers.api.rule=Host(\&amp;#34;api.localhost\&amp;#34;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sample_app
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで &lt;a class="link" href="http://api.localhost/" target="_blank" rel="noopener"
 &gt;http://api.localhost/&lt;/a&gt; に該当のアプリにアクセスすれば繋がると思います。&lt;br&gt;
解説は次に書いてあります。&lt;/p&gt;
&lt;h3 id="docker-compose-での例"&gt;&lt;a href="#docker-compose-%e3%81%a7%e3%81%ae%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;docker-compose での例
&lt;/h3&gt;&lt;p&gt;上記の設定は、&lt;code&gt;docker-compose.yml&lt;/code&gt; で以下のように設定します。&lt;br&gt;
コメントで簡単な解説をつけておきました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Traefik の有効化(exposedByDefault:false に設定した場合に必要)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.enable=true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# api という名前のルーターを定義し、&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# エントリーポイント http (traefik.yml で定義した名前) と関連付け&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.api.entrypoints=http&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ルーター api のホスト名を &amp;#34;api.localhost&amp;#34; に設定&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.api.rule=Host(`api.localhost`)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;基本は以上です。&lt;br&gt;
他の詳細な設定については追々記事を書こうかなと思っています。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://coders-shelf.com/traefik-intro/" target="_blank" rel="noopener"
 &gt;https://coders-shelf.com/traefik-intro/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/adwin/items/ccc34ef5f4c88d8fa02c" target="_blank" rel="noopener"
 &gt;https://qiita.com/adwin/items/ccc34ef5f4c88d8fa02c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/navitime_tech/items/7566bdf80b5a34a86ca8" target="_blank" rel="noopener"
 &gt;https://qiita.com/navitime_tech/items/7566bdf80b5a34a86ca8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://big.tm.land.to/tips/traefik/setup/" target="_blank" rel="noopener"
 &gt;http://big.tm.land.to/tips/traefik/setup/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>MkDocs の設定いろいろ</title><link>https://blog.ponkotools.com/posts/2022/06/03/mkdocs/</link><pubDate>Fri, 03 Jun 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/06/03/mkdocs/</guid><description>&lt;p&gt;MkDocs の細かい設定いろいろです。&lt;/p&gt;
&lt;p&gt;必要に応じて適宜更新していきたいと思います。&lt;/p&gt;
&lt;h2 id="url-を自動でハイパーリンクする"&gt;&lt;a href="#url-%e3%82%92%e8%87%aa%e5%8b%95%e3%81%a7%e3%83%8f%e3%82%a4%e3%83%91%e3%83%bc%e3%83%aa%e3%83%b3%e3%82%af%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;URL を自動でハイパーリンクする
&lt;/h2&gt;&lt;p&gt;以下の拡張機能を有効にします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;markdown_extensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pymdownx.magiclink&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="material-for-mkdocsで打ち消し線が動作するようにする"&gt;&lt;a href="#material-for-mkdocs%e3%81%a7%e6%89%93%e3%81%a1%e6%b6%88%e3%81%97%e7%b7%9a%e3%81%8c%e5%8b%95%e4%bd%9c%e3%81%99%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;Material for MkDocsで打ち消し線が動作するようにする
&lt;/h2&gt;&lt;p&gt;以下の拡張機能を有効にします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;markdown_extensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pymdownx.tilde&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="スペース2個でリストがインデントされるようにする"&gt;&lt;a href="#%e3%82%b9%e3%83%9a%e3%83%bc%e3%82%b92%e5%80%8b%e3%81%a7%e3%83%aa%e3%82%b9%e3%83%88%e3%81%8c%e3%82%a4%e3%83%b3%e3%83%87%e3%83%b3%e3%83%88%e3%81%95%e3%82%8c%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;スペース2個でリストがインデントされるようにする
&lt;/h2&gt;&lt;p&gt;デフォルトではスペース4個でないとリストがインデントされません。&lt;br&gt;
これをスペース2個でもインデントされるようにするには、&lt;code&gt;mdx_truly_sane_lists&lt;/code&gt; という拡張機能をインストールします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pip install mdx_truly_sane_lists
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;mkdocs.yml に以下を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;markdown_extensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;mdx_truly_sane_lists&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nested_indent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="更新日時を表示する"&gt;&lt;a href="#%e6%9b%b4%e6%96%b0%e6%97%a5%e6%99%82%e3%82%92%e8%a1%a8%e7%a4%ba%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;更新日時を表示する
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pip install mkdocs-git-revision-date-localized-plugin
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;search&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;git-revision-date-localized&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Material for MkDocs を使っている場合はこれだけで全ページの下部に更新日時が表示されるようになります。&lt;br&gt;
オプション設定で書式などを変更することもできるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://timvink.github.io/mkdocs-git-revision-date-localized-plugin/options/" target="_blank" rel="noopener"
 &gt;https://timvink.github.io/mkdocs-git-revision-date-localized-plugin/options/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mkdocs/mkdocs/issues/1711" target="_blank" rel="noopener"
 &gt;https://github.com/mkdocs/mkdocs/issues/1711&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kurotori4423.github.io/KurotoriMkDoc/MkDocs%E8%A7%A3%E8%AA%AC/Extension/" target="_blank" rel="noopener"
 &gt;https://kurotori4423.github.io/KurotoriMkDoc/MkDocs%E8%A7%A3%E8%AA%AC/Extension/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stakiran.hatenablog.com/entry/2018/08/02/202816" target="_blank" rel="noopener"
 &gt;https://stakiran.hatenablog.com/entry/2018/08/02/202816&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://roy-n-roy.nyan-co.page/mkdocs/gitRevisionDate/" target="_blank" rel="noopener"
 &gt;https://roy-n-roy.nyan-co.page/mkdocs/gitRevisionDate/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>WebAPI で multipart/form-data を使う</title><link>https://blog.ponkotools.com/posts/2022/06/02/python/</link><pubDate>Thu, 02 Jun 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/06/02/python/</guid><description>&lt;p&gt;AI を使った画像解析システムなどでは、画像をリクエストで投げて推論結果をレスポンスでもらう、というのをよくやるかと思います。&lt;/p&gt;
&lt;p&gt;そういった API で、最初は画像を Base64 に変換して JSON で渡していたのですが、エンコード/デコードの処理時間があるため、バイナリでデータを送りたいと考えました。&lt;br&gt;
また、１度のリクエストで複数枚の画像を送る必要があるのと、画像の対する付加情報（カメラのIDや画像の取得日時など）も一緒に渡す必要があるということで、&lt;code&gt;multipart/form-data&lt;/code&gt; を使って送ってみることにしました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;multipart/form-data&lt;/code&gt; についての詳細は割愛しますが、バウンダリ文字列で区切って複数のデータを送信するやつで、HTML の form 文とかで使われるやつです。&lt;/p&gt;
&lt;p&gt;今まで WebAPI では json と yaml しか扱ったことありませんでしたが、調べた感じ、WebAPI でも &lt;code&gt;multipart/form-data&lt;/code&gt; を使ってテキストとバイナリを一緒に送るというのはよくある手法っぽいです。&lt;/p&gt;
&lt;h2 id="リクエスト内容"&gt;&lt;a href="#%e3%83%aa%e3%82%af%e3%82%a8%e3%82%b9%e3%83%88%e5%86%85%e5%ae%b9" class="header-anchor"&gt;&lt;/a&gt;リクエスト内容
&lt;/h2&gt;&lt;p&gt;例として、POST で以下のような内容を送ります。&lt;/p&gt;
&lt;h3 id="ヘッダー抜粋"&gt;&lt;a href="#%e3%83%98%e3%83%83%e3%83%80%e3%83%bc%e6%8a%9c%e7%b2%8b" class="header-anchor"&gt;&lt;/a&gt;ヘッダー（抜粋）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type multipart/form-data; boundary=cc874efaa4e6a1e85c14280c96a7b237
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;サンプルコードを後に載せていますが、バウンダリ文字列は自動生成でリクエスト毎に異なります。&lt;br&gt;
基本的に意識しなくても大丈夫でした。&lt;/p&gt;
&lt;h3 id="ペイロード"&gt;&lt;a href="#%e3%83%9a%e3%82%a4%e3%83%ad%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;ペイロード
&lt;/h3&gt;&lt;p&gt;テキストについては一つずつ &lt;code&gt;text/plain&lt;/code&gt; で送ろうかとも思いましたが、今後データが増えた時にサーバー側の処理が面倒かなと思い、JSON にまとめることにしました。&lt;br&gt;
画像データ以外は JSON でまとめて送り、画像データはバイナリで送ります。&lt;br&gt;
これをカメラ台数分送ります。
カメラ毎に JSON と画像をマッピングする必要がありますが、試行錯誤した結果、&lt;code&gt;name&lt;/code&gt; にカメラを識別するためのIDを設定することにしました。
つまり、&lt;code&gt;name&lt;/code&gt; の値を見てどのカメラの JSON データ、画像データかを識別する想定です。&lt;br&gt;
後述するサンプルコードで試した結果、ペイロードは以下のような形になりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--cc874efaa4e6a1e85c14280c96a7b237
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Disposition: form-data; name=&amp;#34;カメラのID&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;camera_id&amp;#34;: &amp;#34;1&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;datetime&amp;#34;: &amp;#34;2021-08-05T17:07:01.388437&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--cc874efaa4e6a1e85c14280c96a7b237
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Disposition: form-data; name=&amp;#34;カメラのID&amp;#34;; filename=&amp;#34;ファイル名&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: image/jpeg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;ここに画像のバイナリデータが入る&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--cc874efaa4e6a1e85c14280c96a7b237--
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;複数カメラ分のデータを送信した場合、並びは以下ようになりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;１台目のカメラの JSON データ&lt;/li&gt;
&lt;li&gt;２台目のカメラの JSON データ&lt;/li&gt;
&lt;li&gt;１台目のカメラの画像データ&lt;/li&gt;
&lt;li&gt;２台目のカメラの画像データ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;name&lt;/code&gt; でどのカメラかを判別できるので、基本的にこの並びは意識しなくても大丈夫でした。&lt;/p&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;p&gt;Python での実装例です。&lt;/p&gt;
&lt;h3 id="クライアント側"&gt;&lt;a href="#%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e5%81%b4" class="header-anchor"&gt;&lt;/a&gt;クライアント側
&lt;/h3&gt;&lt;p&gt;上記のリクエストを &lt;code&gt;requests&lt;/code&gt; モジュールを使って送信するサンプルです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 複数カメラを想定して送信&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;camera_id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hoge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;piyo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="c1"&gt;# 各カメラのID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 適当なテキストデータ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;json_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;camera_id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;camera_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;datetime&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 適当な画像ファイルを読み込む&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;send_image.jpg&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rb&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 送信&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# data,files は dict 型でなければならないので、カメラIDをキーとして渡すことにした。このキーが name に設定される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;camera_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;# dict -&amp;gt; str への変換&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# filename や Content-Type を指定して送りたい場合&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;camera_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;image/jpeg&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 画像のみで送りたい場合。filename は name と同じになり、Content-Type は付与されなかった&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#files[camera_id] = image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://localhost:8000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="サーバー側"&gt;&lt;a href="#%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc%e5%81%b4" class="header-anchor"&gt;&lt;/a&gt;サーバー側
&lt;/h3&gt;&lt;p&gt;上記のリクエストを Flask で受信するサンプルです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;POST&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#print(request.get_data()) # 生データ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# JSON データの受け取り&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;json_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# str から dict への変換&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;json, key=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;:, value=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;json_data&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, type=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 画像データの受け取り&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;image, key=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, type=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# FileStorage 型&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#print(value.headers)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ファイルに保存して確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;.jpg&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;wb&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ファイルの保存だけなら以下でも可&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#value.save(f&amp;#39;{key}.jpg&amp;#39;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="openapi-で-multipartform-data-を記述する"&gt;&lt;a href="#openapi-%e3%81%a7-multipartform-data-%e3%82%92%e8%a8%98%e8%bf%b0%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;OpenAPI で multipart/form-data を記述する
&lt;/h2&gt;&lt;p&gt;OpenAPI で API の仕様書を作成しているのですが、&lt;code&gt;multipart/form-data&lt;/code&gt; は以下のように記述するようです。&lt;br&gt;
ただ、上述したような &lt;code&gt;name&lt;/code&gt; をカメラのIDとするような記述はできないようです。&lt;br&gt;
ここでは &lt;code&gt;json_data&lt;/code&gt; &lt;code&gt;image&lt;/code&gt; という値で記述しています。&lt;/p&gt;
&lt;p&gt;また、&lt;code&gt;Content-Type&lt;/code&gt; を記述したい場合は &lt;code&gt;encoding&lt;/code&gt; を使うそうですが、Swagger で試しに送信しても付与されていませんでした。
あと、Redoc ではリクエストボディの内容が表示されませんでした。&lt;br&gt;
``multipart/form-data` 自体に対応していないのかもしれません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;/endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;post&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;サンプル&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;説明&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requestBody&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;multipart/form-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;object&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;json_data&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;image&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;object&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;camera_id&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;datetime&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;画像以外のデータ(JSON)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;camera_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;カメラの識別子&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;example&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hoge&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;date-time&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;画像の取得日時(ISO8601)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;example&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2021-08-05T17:07:01.388437&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;binary&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;画像データ(バイナリ)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;encoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;image/jpeg;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://raahii.github.io/posts/files-upload/" target="_blank" rel="noopener"
 &gt;https://raahii.github.io/posts/files-upload/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://swagger.io/docs/specification/describing-request-body/multipart-requests/" target="_blank" rel="noopener"
 &gt;https://swagger.io/docs/specification/describing-request-body/multipart-requests/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.yoheim.net/blog.php?q=20171201" target="_blank" rel="noopener"
 &gt;https://www.yoheim.net/blog.php?q=20171201&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/Redocly/redoc/issues/707" target="_blank" rel="noopener"
 &gt;https://github.com/Redocly/redoc/issues/707&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/springdoc/springdoc-openapi/issues/396" target="_blank" rel="noopener"
 &gt;https://github.com/springdoc/springdoc-openapi/issues/396&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://max999blog.com/python-how-to-post-json-and-file-same-time/" target="_blank" rel="noopener"
 &gt;https://max999blog.com/python-how-to-post-json-and-file-same-time/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://cpoint-lab.co.jp/article/201902/7860/" target="_blank" rel="noopener"
 &gt;https://cpoint-lab.co.jp/article/201902/7860/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Portainer を Docker Swarm で動かす</title><link>https://blog.ponkotools.com/posts/2022/05/27/portainer-docker-swarm/</link><pubDate>Fri, 27 May 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/05/27/portainer-docker-swarm/</guid><description>&lt;p&gt;以前 Portainer を docker-compose で動かしました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/04/portainer-docker-compose.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/04/portainer-docker-compose.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回はこの Portainer を Docker Swarm が有効になっている環境で動かしてみます。&lt;br&gt;
クラスタを構成している全ノードが Portainer で管理できるようになります。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Docker 20.10.12&lt;/li&gt;
&lt;li&gt;Portainer 2.13.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="docker-swarm-の有効化"&gt;&lt;a href="#docker-swarm-%e3%81%ae%e6%9c%89%e5%8a%b9%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;Docker Swarm の有効化
&lt;/h2&gt;&lt;p&gt;以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker swarm init
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちょっと試すだけならばここまでで OK です。&lt;br&gt;
必要なら worker ノードの追加なども行ってください。&lt;/p&gt;
&lt;h2 id="portainer-の起動"&gt;&lt;a href="#portainer-%e3%81%ae%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;Portainer の起動
&lt;/h2&gt;&lt;p&gt;公式ドキュメントが以下になります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.portainer.io/v/ce-2.9/start/install/agent/swarm/linux" target="_blank" rel="noopener"
 &gt;https://docs.portainer.io/v/ce-2.9/start/install/agent/swarm/linux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;こちらに yml ファイルの置き場所が記載されているので、Community Edition のほうのファイルをダウンロードします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -L https://downloads.portainer.io/ce2-13/portainer-agent-stack.yml -o portainer-agent-stack.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;中身はこんな感じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;3.2&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;portainer/agent:2.13.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;/var/lib/docker/volumes:/var/lib/docker/volumes&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;agent_network&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;global&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;placement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;node.platform.os == linux]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;portainer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;portainer/portainer-ce:2.13.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="l"&gt;H tcp://tasks.agent:9001 --tlsskipverify&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;9443:9443&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;9000:9000&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;8000:8000&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;portainer_data:/data&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;agent_network&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;replicated&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;placement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;node.role == manager]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;agent_network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;overlay&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;attachable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;portainer_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これを &lt;code&gt;docker stack deploy&lt;/code&gt; で起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack deploy -c portainer-agent-stack.yml portainer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating network portainer_agent_network
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating service portainer_agent
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating service portainer_portainer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以上で完了です。&lt;br&gt;
あとは http://localhost:9000 にアクセスすれば OK です。&lt;/p&gt;
&lt;p&gt;起動した portainer を停止・削除したい場合は以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack rm portainer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.portainer.io/v/ce-2.9/start/install/agent/swarm/linux" target="_blank" rel="noopener"
 &gt;https://docs.portainer.io/v/ce-2.9/start/install/agent/swarm/linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/polarbear08/items/931fe04ec228fad13092" target="_blank" rel="noopener"
 &gt;https://qiita.com/polarbear08/items/931fe04ec228fad13092&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Docker コンテナ内から Docker コマンドを使う</title><link>https://blog.ponkotools.com/posts/2022/05/26/docker/</link><pubDate>Thu, 26 May 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/05/26/docker/</guid><description>&lt;p&gt;Docker コンテナ内のアプリケーションから Docker コンテナの操作をしたかったので、やってみました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Docker 20.10.12&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dind-と-dood"&gt;&lt;a href="#dind-%e3%81%a8-dood" class="header-anchor"&gt;&lt;/a&gt;DinD と DooD
&lt;/h2&gt;&lt;p&gt;Docker コンテナ内から Docker を扱う方法としては以下の２つがあるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DinD: Docker in Docker
&lt;ul&gt;
&lt;li&gt;Docker コンテナの中で Docker デーモンを動かす&lt;/li&gt;
&lt;li&gt;コンテナの中にコンテナを作成したりできる&lt;/li&gt;
&lt;li&gt;非推奨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DooD: Docker outside of Docker
&lt;ul&gt;
&lt;li&gt;ホストの docker.sock をコンテナにマウントし、Docker デーモンを共有する&lt;/li&gt;
&lt;li&gt;ホスト上の Docker コンテナを操作できる&lt;/li&gt;
&lt;li&gt;基本的にこちらを使う&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ここらへん以下のページが分かりやすかったです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/YukiMiyatake/items/2e68aa69a5ca3921d55d" target="_blank" rel="noopener"
 &gt;https://qiita.com/YukiMiyatake/items/2e68aa69a5ca3921d55d&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;DinD は Docker の開発用途のためのものらしく、セキュリティリスクなどもあることから非推奨で、基本的には DooD のほうを使うべきだそうです。&lt;br&gt;
今回の用途的にも DooD のほうなので、DooD を試してみました。&lt;/p&gt;
&lt;h2 id="dood-サンプル"&gt;&lt;a href="#dood-%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;DooD サンプル
&lt;/h2&gt;&lt;p&gt;ググってみると以下のようなサンプルが多いです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run -it -v /var/run/docker.sock:/var/run/docker.sock docker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;確かにこれでコンテナ内で docker コマンドが使えました。&lt;br&gt;
この場合では &lt;code&gt;docker&lt;/code&gt; という Docker 一式が入ったイメージを使っているので、&lt;code&gt;/var/run/docker.sock&lt;/code&gt; をマウントするだけで使えています。&lt;/p&gt;
&lt;p&gt;しかし、実際にはアプリケーションのランタイムイメージをベースとすることが多いと思います。&lt;br&gt;
試しに Ubuntu のイメージを使うと、以下のようにエラーになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run -it -v /var/run/docker.sock:/var/run/docker.sock ubuntu:20.04
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# docker ps&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bash: docker: &lt;span class="nb"&gt;command&lt;/span&gt; not found
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Docker クライアントがインストールされていないからです。&lt;/p&gt;
&lt;p&gt;この場合、コンテナ内で &lt;code&gt;docker.io&lt;/code&gt; をインストールすれば docker コマンドが使えるようになります。&lt;br&gt;
ついでに &lt;code&gt;docker-compose&lt;/code&gt; もインストールしています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install -y docker.io docker-compose
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;というわけで、DooD では&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/var/run/docker.sock&lt;/code&gt; をマウント&lt;/li&gt;
&lt;li&gt;ベースイメージに Docker クライアントがインストールされていなければインストール&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;で、コンテナ内から Docker コマンドが使えるようになります。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/YukiMiyatake/items/2e68aa69a5ca3921d55d" target="_blank" rel="noopener"
 &gt;https://qiita.com/YukiMiyatake/items/2e68aa69a5ca3921d55d&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/minamijoyo/items/c937fb4f646dc1ff064a" target="_blank" rel="noopener"
 &gt;https://qiita.com/minamijoyo/items/c937fb4f646dc1ff064a&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.mtioutput.com/entry/docker-outside-of" target="_blank" rel="noopener"
 &gt;https://www.mtioutput.com/entry/docker-outside-of&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://devblog.pirika.org/entry/2021/10/05/113000" target="_blank" rel="noopener"
 &gt;https://devblog.pirika.org/entry/2021/10/05/113000&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>OpenAPI + Swagger + Redoc + GitLab Pages で API ドキュメントを管理する</title><link>https://blog.ponkotools.com/posts/2022/05/24/openapi/</link><pubDate>Tue, 24 May 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/05/24/openapi/</guid><description>&lt;p&gt;APIドキュメントを簡単に作成・閲覧できるようにしたいと思い、OpenAPI で作成、Swagger および Redoc で表示、GitLab Pages で公開までを行いました。&lt;/p&gt;
&lt;h2 id="概要"&gt;&lt;a href="#%e6%a6%82%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;概要
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;OpenAPI で yaml を作成&lt;/li&gt;
&lt;li&gt;GitLab CI/CD により自動で Swagger および Redoc でビルドし、GitLab Pages に公開&lt;/li&gt;
&lt;li&gt;ローカル環境用に Swagger および Redoc を Docker で動かす&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ディレクトリ構造"&gt;&lt;a href="#%e3%83%87%e3%82%a3%e3%83%ac%e3%82%af%e3%83%88%e3%83%aa%e6%a7%8b%e9%80%a0" class="header-anchor"&gt;&lt;/a&gt;ディレクトリ構造
&lt;/h2&gt;&lt;p&gt;今回試しに作成したファイル一式は以下となります。
詳細は後述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree -a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── .gitlab-ci.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── README.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── openapi
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └── openapi.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── public
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── index.html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="openapi-の-yaml-を作成"&gt;&lt;a href="#openapi-%e3%81%ae-yaml-%e3%82%92%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;OpenAPI の yaml を作成
&lt;/h2&gt;&lt;p&gt;Open API Specification (OAS) は REST API の仕様を記述するフォーマットです。
記述方法についてはググったらたくさん出てくるので割愛します。&lt;/p&gt;
&lt;p&gt;例えば、以下のような yaml を作成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;openapi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3.0.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;info&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1.0.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;OpenAPI Sample&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;/users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Get Users&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#39;200&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;OK&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="ローカル環境の作成"&gt;&lt;a href="#%e3%83%ad%e3%83%bc%e3%82%ab%e3%83%ab%e7%92%b0%e5%a2%83%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;ローカル環境の作成
&lt;/h2&gt;&lt;p&gt;ひとまず GitLab は置いておき、まずはローカル環境で Swagger および Redoc が動くようにしてみます。&lt;br&gt;
３つのサービスを動かしたかったので、docker-compose 使いました。&lt;br&gt;
作成した docker-compose.yml は以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;3&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# エディター&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;swagger-editor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;swaggerapi/swagger-editor&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;8081:8080&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ビューワー（Swagger-UI 版）&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;swagger-ui&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;swaggerapi/swagger-ui&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./openapi:/usr/share/nginx/html/openapi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;API_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./openapi/openapi.yaml&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Swagger UIの画面を開いたときに初期値として表示するファイル&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s1"&gt;&amp;#39;8082:8080&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ビューワー（Redoc 版）&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;redoc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;redocly/redoc&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./openapi:/usr/share/nginx/html/openapi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;SPEC_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./openapi/openapi.yaml&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Redocの画面を開いたときに初期値として表示するファイル&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# nginx port(default:80)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s1"&gt;&amp;#39;8083:8080&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;特に難しいところはないかと思います。&lt;br&gt;
&lt;code&gt;docker-compose up&lt;/code&gt; で動かしたあと、ブラウザでアクセスすればOKです。&lt;/p&gt;
&lt;p&gt;http://localhost:8081 で Swagger Editor にアクセスして編集が行えます。&lt;br&gt;
http://localhost:8082 で Swagger UI での表示を確認できます。&lt;br&gt;
http://localhost:8083 で Redoc での表示を確認できます。&lt;/p&gt;
&lt;p&gt;ただ、Swagger Editor は別にいらなかったかもしれません。&lt;br&gt;
私の場合、結局 VSCode で yaml を編集し、ブラウザの表示を更新して確認、ってやってます。&lt;/p&gt;
&lt;p&gt;閲覧に関しては Swagger より Redoc のほうが個人的に見やすいですね。&lt;/p&gt;
&lt;h2 id="gitlab-pages-で公開する"&gt;&lt;a href="#gitlab-pages-%e3%81%a7%e5%85%ac%e9%96%8b%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;GitLab Pages で公開する
&lt;/h2&gt;&lt;p&gt;ローカルでの環境は以上で整ったので、次は GitLab に push したら自動ビルドを行って GitLab Pages に公開するように設定します。&lt;br&gt;
GitLab Pages や GitLab CI/CD については割愛します。&lt;/p&gt;
&lt;p&gt;Swagger + GitLab Pages については以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://lab.astamuse.co.jp/entry/2019/11/13/114500" target="_blank" rel="noopener"
 &gt;https://lab.astamuse.co.jp/entry/2019/11/13/114500&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ただ、今回 swagger-ui-dist のバージョンを上げたので、&lt;code&gt;sed&lt;/code&gt; コマンドで修正するファイルを &lt;code&gt;index.html&lt;/code&gt; から &lt;code&gt;swagger-initializer.js&lt;/code&gt; に変更する必要がありました。&lt;br&gt;
これについては以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/hidao/items/d13e7dda3da02d37dd45" target="_blank" rel="noopener"
 &gt;https://qiita.com/hidao/items/d13e7dda3da02d37dd45&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Redoc + GitLab Pages については以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://medium.com/hoursofoperation/auto-generate-swagger-docs-to-gitlab-pages-ca040230df3a" target="_blank" rel="noopener"
 &gt;https://medium.com/hoursofoperation/auto-generate-swagger-docs-to-gitlab-pages-ca040230df3a&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上の２つを組み合わせ、最終的に作成した .gitlab-ci.yml は以下です。&lt;br&gt;
Swagger と Redoc のそれぞれで閲覧できるようにディレクトリを分けてみました。&lt;br&gt;
プロキシ環境下でなければプロキシ関係の設定は不要です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;node:18-alpine&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# プロキシサーバー&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;PROXY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://example:8080&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ドキュメントのあるディレクトリ&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DOCS_FOLDER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;swagger&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ドキュメントファイル&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;SPEC_TO_DISPLAY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;openapi.yaml&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# デプロイ先&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DEPLOY_SWAGGER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;public/swagger&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DEPLOY_REDOC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;public/redoc&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./node_modules&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;deploy&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;before_script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# プロキシ環境下での下準備&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;npm -g config set proxy $PROXY&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;npm -g config set https-proxy $PROXY&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;npm -g config set registry http://registry.npmjs.org/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;npm config set strict-ssl false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Swagger UI&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;npm install swagger-ui-dist@4.11.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Redoc&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;npm install -g redoc-cli@0.13.14&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mkdir -p $DEPLOY_SWAGGER&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mkdir -p $DEPLOY_REDOC&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Swagger UI&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;cp -rp node_modules/swagger-ui-dist/* $DEPLOY_SWAGGER&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;cp -rp $DOCS_FOLDER/* $DEPLOY_SWAGGER&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sed -i &amp;#34;s#https://petstore\.swagger\.io/v2/swagger\.json#$SPEC_TO_DISPLAY#g&amp;#34; $DEPLOY_SWAGGER/swagger-initializer.js&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Redoc&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;redoc-cli build -o $DEPLOY_REDOC/index.html $DOCS_FOLDER/$SPEC_TO_DISPLAY&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;artifacts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;public&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちなみに、Swagger の yaml ファイルは GitLab 上で Swagger でプレビュー表示されるので、外部に公開する必要がなければこれで十分かもしれません。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.kyanny.me/entry/2020/08/06/012807" target="_blank" rel="noopener"
 &gt;https://blog.kyanny.me/entry/2020/08/06/012807&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://medium.com/hoursofoperation/auto-generate-swagger-docs-to-gitlab-pages-ca040230df3a" target="_blank" rel="noopener"
 &gt;https://medium.com/hoursofoperation/auto-generate-swagger-docs-to-gitlab-pages-ca040230df3a&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://overworker.hatenablog.jp/entry/2020/08/10/172207" target="_blank" rel="noopener"
 &gt;https://overworker.hatenablog.jp/entry/2020/08/10/172207&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/WinterYukky/items/366ed76dd4763a9b01e0" target="_blank" rel="noopener"
 &gt;https://qiita.com/WinterYukky/items/366ed76dd4763a9b01e0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://lab.astamuse.co.jp/entry/2019/11/13/114500" target="_blank" rel="noopener"
 &gt;https://lab.astamuse.co.jp/entry/2019/11/13/114500&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.kyanny.me/entry/2020/08/06/012807" target="_blank" rel="noopener"
 &gt;https://blog.kyanny.me/entry/2020/08/06/012807&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>MkDocs + GitLab Pages でドキュメント管理</title><link>https://blog.ponkotools.com/posts/2022/05/23/mkdocs/</link><pubDate>Mon, 23 May 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/05/23/mkdocs/</guid><description>&lt;p&gt;マークダウンで書いたドキュメントを簡単に管理・閲覧できるようにしたいと思い、MkDocs と GitLab Pages を使ってみました。&lt;/p&gt;
&lt;h2 id="概要"&gt;&lt;a href="#%e6%a6%82%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;概要
&lt;/h2&gt;&lt;p&gt;Markdown で書いたドキュメントを MkDocs を使って静的サイトに変換します。&lt;br&gt;
MkDocs のビルドは GitLab CI/CD を使って自動で行い、出力された静的サイトを GitLab Pages で公開します。&lt;br&gt;
また、ローカル環境での確認用に、Docker を使って MkDocs が動作する環境を作成します。&lt;/p&gt;
&lt;p&gt;GitLab-Runner の設定は済んでいる前提です。&lt;/p&gt;
&lt;h2 id="ローカル環境の構築"&gt;&lt;a href="#%e3%83%ad%e3%83%bc%e3%82%ab%e3%83%ab%e7%92%b0%e5%a2%83%e3%81%ae%e6%a7%8b%e7%af%89" class="header-anchor"&gt;&lt;/a&gt;ローカル環境の構築
&lt;/h2&gt;&lt;p&gt;ひとまず GitLab は置いておき、まずはローカル環境で MkDocs が動くようにしてみます。&lt;br&gt;
作成した Dockerfile は以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;FROM python:3.9-slim
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RUN pip install \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mkdocs \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mkdocs-material \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; pygments
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CMD [&amp;#34;mkdocs&amp;#34;, &amp;#34;serve&amp;#34;, &amp;#34;-a&amp;#34;, &amp;#34;0.0.0.0:8000&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ビルドします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker build -t mkdocs .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ドキュメントの新規作成初回のみ"&gt;&lt;a href="#%e3%83%89%e3%82%ad%e3%83%a5%e3%83%a1%e3%83%b3%e3%83%88%e3%81%ae%e6%96%b0%e8%a6%8f%e4%bd%9c%e6%88%90%e5%88%9d%e5%9b%9e%e3%81%ae%e3%81%bf" class="header-anchor"&gt;&lt;/a&gt;ドキュメントの新規作成（初回のみ）
&lt;/h3&gt;&lt;p&gt;ドキュメントを何も作成していない状態でコンテナを起動するとエラーとなります。&lt;br&gt;
まずはコンテナ起動時に &lt;code&gt;mkdocs new doc&lt;/code&gt; を実行してドキュメントを新規作成しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -it --rm \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -u &amp;#34;$(id -u $USER):$(id -g $USER)&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v $(pwd)/workspace:/workspace \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --workdir=&amp;#34;/workspace&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mkdocs mkdocs new doc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下のようにファイルが作成されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tree workspace/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;workspace/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── doc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── docs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │   └── index.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── mkdocs.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="コンテナの起動"&gt;&lt;a href="#%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e3%81%ae%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;コンテナの起動
&lt;/h3&gt;&lt;p&gt;ドキュメント作成済みであれば、以下のようにしてコンテナを起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -it --rm &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -u &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;id -u &lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;id -g &lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v &lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;/workspace:/workspace &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -p 8000:8000 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --workdir&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/workspace/doc&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mkdocs
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ブラウザで http://localhost:8000 にアクセスすれば MkDocs のページが表示されます。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="467px" data-flex-grow="194" height="625" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/05/23/mkdocs/01.webp" srcset="https://blog.ponkotools.com/posts/2022/05/23/mkdocs/01_hu_909a3887eac5dca2.webp 800w, https://blog.ponkotools.com/posts/2022/05/23/mkdocs/01.webp 1217w" width="1217"&gt;&lt;/p&gt;
&lt;h2 id="gitlab-pages-で公開する"&gt;&lt;a href="#gitlab-pages-%e3%81%a7%e5%85%ac%e9%96%8b%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;GitLab Pages で公開する
&lt;/h2&gt;&lt;p&gt;ローカルでの環境は以上で整ったので、次は GitLab に push したら MkDocs のビルドを行って GitLab Pages に公開するように設定します。&lt;br&gt;
作成した &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; は以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;python:3.9-slim&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;before_script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pip install --upgrade pip&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pip install mkdocs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pip install mkdocs-material&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;pip install pygments&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;build&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;cd workspace/doc&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mkdocs build&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mv site ../../public&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;artifacts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;public&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;特に難しいところはないかと思います。&lt;br&gt;
&lt;code&gt;mkdocs build&lt;/code&gt; でビルドすると &lt;code&gt;site&lt;/code&gt; に出力されるので、&lt;code&gt;public&lt;/code&gt; にリネームして GitLab Pages に公開しています。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/hykisk/items/ebff2f7cd2e8100a6bbe" target="_blank" rel="noopener"
 &gt;https://qiita.com/hykisk/items/ebff2f7cd2e8100a6bbe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kurotorimkdocs.gitlab.io/kurotorimemo/040-Documents/MkDocs/mkdocsGitLab/" target="_blank" rel="noopener"
 &gt;https://kurotorimkdocs.gitlab.io/kurotorimemo/040-Documents/MkDocs/mkdocsGitLab/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Ubuntu の IP アドレスを固定化する</title><link>https://blog.ponkotools.com/posts/2022/05/20/ubuntu/</link><pubDate>Fri, 20 May 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/05/20/ubuntu/</guid><description>&lt;p&gt;いつもは GUI で設定するのですが、あるとき IP アドレスを変更しても再起動後に元に戻ってしまうという現象が発生して悩んでいました。&lt;br&gt;
調べたら他の人が IP アドレスを固定化してたのが原因だとわかったので、ついでにそのやり方をメモしておきます。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="設定方法"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;設定方法
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;/etc/netplan/&lt;/code&gt; に yaml ファイルを作成します。&lt;/p&gt;
&lt;p&gt;ここに作成したファイルが名前順に読み込まれ、後に読み込まれた内容のほうが優先されるようです。&lt;/p&gt;
&lt;p&gt;Ubuntu Desktop の場合、デフォルトで &lt;code&gt;01-network-manager-all.yaml&lt;/code&gt; があり、ネットワークマネージャーでの設定が反映されるようになっています。&lt;/p&gt;
&lt;p&gt;IP アドレスを固定化したい場合は、&lt;code&gt;/etc/netplan/99_config.yaml&lt;/code&gt; など、後に読み込まれるようなファイル名でファイルを作成し、設定を上書きしてやるそうです。&lt;br&gt;
yaml ファイルの書き方なども含め、公式ドキュメントは以下になります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://ubuntu.com/server/docs/network-configuration" target="_blank" rel="noopener"
 &gt;https://ubuntu.com/server/docs/network-configuration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例えば以下のような感じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ethernets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;eth0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;addresses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;192.168.1.10&lt;/span&gt;&lt;span class="l"&gt;/24&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;gateway4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192.168.1.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;optional&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://ubuntu.com/server/docs/network-configuration" target="_blank" rel="noopener"
 &gt;https://ubuntu.com/server/docs/network-configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://tarufu.info/how_to_assign_static_ip_address_on_ubuntu/" target="_blank" rel="noopener"
 &gt;https://tarufu.info/how_to_assign_static_ip_address_on_ubuntu/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://www2.yukawa.kyoto-u.ac.jp/~koudai.sugimoto/dokuwiki/doku.php?id=%E8%87%AA%E4%BD%9C%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E8%A8%88%E7%AE%97%E6%A9%9F:%E5%9B%BA%E5%AE%9Aip%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%AE%E8%A8%AD%E5%AE%9A" target="_blank" rel="noopener"
 &gt;http://www2.yukawa.kyoto-u.ac.jp/~koudai.sugimoto/dokuwiki/doku.php?id=%E8%87%AA%E4%BD%9C%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E8%A8%88%E7%AE%97%E6%A9%9F:%E5%9B%BA%E5%AE%9Aip%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%AE%E8%A8%AD%E5%AE%9A&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Redmine のチケットを一括で他のプロジェクトに移動させる</title><link>https://blog.ponkotools.com/posts/2022/05/17/redmine/</link><pubDate>Tue, 17 May 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/05/17/redmine/</guid><description>&lt;p&gt;ちょっとだけ迷ったのでメモです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;チケットの一覧で、チケットを複数選択&lt;/li&gt;
&lt;li&gt;右クリックして「編集」を選択&lt;/li&gt;
&lt;li&gt;プロジェクトを変更する&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://linkerdesign.github.io/journal/2013/01/redmine.html" target="_blank" rel="noopener"
 &gt;https://linkerdesign.github.io/journal/2013/01/redmine.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Redmine に Git のリポジトリを追加したら internal error が表示される</title><link>https://blog.ponkotools.com/posts/2022/05/13/redmine/</link><pubDate>Fri, 13 May 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/05/13/redmine/</guid><description>&lt;p&gt;私の場合ですが、タグ名に日本語を使っていたのが原因のようでした。&lt;/p&gt;
&lt;p&gt;環境は以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Redmine 3.4.2&lt;/li&gt;
&lt;li&gt;Git 1.8.3.1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ちょっと古いバージョンなので最新バージョンではわかりませんが、この環境下では、ブランチやタグの名前に日本語を使っていると internal error となるようです。&lt;br&gt;
Redmine のログを見ていてタグの表示でエラーになっているっぽかったので気が付きました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://plugins.co.jp/2015/05/git%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AB%E6%97%A5%E6%9C%AC%E8%AA%9E%E5%90%8D%E3%82%92%E3%81%A4%E3%81%91%E3%82%8B%E3%81%A8redmine%E3%81%AE%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA/" target="_blank" rel="noopener"
 &gt;https://plugins.co.jp/2015/05/git%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AB%E6%97%A5%E6%9C%AC%E8%AA%9E%E5%90%8D%E3%82%92%E3%81%A4%E3%81%91%E3%82%8B%E3%81%A8redmine%E3%81%AE%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Redmine に Git のリポジトリを追加したら 404 エラーが表示される</title><link>https://blog.ponkotools.com/posts/2022/05/12/redmine/</link><pubDate>Thu, 12 May 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/05/12/redmine/</guid><description>&lt;p&gt;まずはファイルパスが正しいかを疑うべきですが、それが正しい場合はアクセス権が原因の可能性があります。&lt;/p&gt;
&lt;p&gt;例えば、私の場合、&lt;code&gt;/home/username/xxxx.git&lt;/code&gt; という場所にベアリポジトリを作成していたのですが、&lt;code&gt;xxxx.git&lt;/code&gt; のアクセス権しか変更していませんでした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo chmod o+rx xxxx.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;しかし、その一つ上の &lt;code&gt;/home/username&lt;/code&gt; にアクセス権が設定されていなかったため、Redmine からは見ることができなかったようです。&lt;br&gt;
以下のように設定変更すれば解決しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo chmod o+rx /home/username
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.pistolfly.com/weblog/2010/11/redminegit.html" target="_blank" rel="noopener"
 &gt;https://www.pistolfly.com/weblog/2010/11/redminegit.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>GitLab でプライベートリポジトリの分も草を生やす</title><link>https://blog.ponkotools.com/posts/2022/05/02/gitlab/</link><pubDate>Mon, 02 May 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/05/02/gitlab/</guid><description>&lt;p&gt;GitLab のプロフィールに表示されるコミットグラフですが、デフォルトでは自分以外の人からは Public なリポジトリの分しか見えません。&lt;/p&gt;
&lt;p&gt;Private なリポジトリのコミット分も見えるようにするには、以下の設定を変更します。&lt;/p&gt;
&lt;p&gt;Preferences &amp;gt; Profile &amp;gt; Private contributions&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.igorkromin.net/index.php/2018/09/13/gitlab-finally-shows-private-project-contributions-in-the-profile-commit-graph/" target="_blank" rel="noopener"
 &gt;https://www.igorkromin.net/index.php/2018/09/13/gitlab-finally-shows-private-project-contributions-in-the-profile-commit-graph/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Jetson Xavier NX を触ってみた</title><link>https://blog.ponkotools.com/posts/2022/04/28/jetson/</link><pubDate>Thu, 28 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/28/jetson/</guid><description>&lt;p&gt;Jetson Xavier NX を搭載したボックスコンピューターを触る機会があったのでメモです。&lt;/p&gt;
&lt;p&gt;ボックスコンピューターは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.aaeon.com/jp/p/nvidia-jetson-xavier-nx-ai-edge-poe-boxer-8253ai" target="_blank" rel="noopener"
 &gt;https://www.aaeon.com/jp/p/nvidia-jetson-xavier-nx-ai-edge-poe-boxer-8253ai&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CUDA や Docker は最初からインストールされていました。&lt;/p&gt;
&lt;p&gt;ゴールとしては Docker コンテナ上で GPU を使って推論を行うことです。&lt;/p&gt;
&lt;p&gt;先に結論を書いておくと、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CPU アーキテクチャが arm なので、arm に対応したベースイメージを使う必要がある&lt;/li&gt;
&lt;li&gt;Jetson は GPU ドライバーの都合上、現時点で CUDA 11 以降に対応していない
&lt;ul&gt;
&lt;li&gt;インストールされているバージョンは 10.2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;つまり、arm で CUDA 10.2 のイメージを使う必要があるが、Docker Hub にはその組み合わせの公式イメージがない&lt;/li&gt;
&lt;li&gt;NVIDIA GPU CLOUD (NGC) にある &lt;code&gt;l4t-ml:r32.5.0-py3&lt;/code&gt; のイメージを使えばいいとのこと
&lt;ul&gt;
&lt;li&gt;これが Jetson Xavier NX にインストールされている JetPack と同等のイメージになる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="jetson-jetpack-l4t-について調べてみた"&gt;&lt;a href="#jetson-jetpack-l4t-%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6%e8%aa%bf%e3%81%b9%e3%81%a6%e3%81%bf%e3%81%9f" class="header-anchor"&gt;&lt;/a&gt;Jetson, JetPack, L4T について調べてみた
&lt;/h2&gt;&lt;p&gt;ここらへんの関係がよくわからなかったので、少し調べてみました。&lt;/p&gt;
&lt;p&gt;NVIDIA Jetson シリーズは JetPack という形で、OS、NVIDIA ドライバー、CUDA や cuDNN などのフレームワークも含めた形で提供されているらしいです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://developer.nvidia.com/ja-jp/embedded/jetpack" target="_blank" rel="noopener"
 &gt;https://developer.nvidia.com/ja-jp/embedded/jetpack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://ja.wikipedia.org/wiki/NVIDIA_Jetson#Xavier" target="_blank" rel="noopener"
 &gt;https://ja.wikipedia.org/wiki/NVIDIA_Jetson#Xavier&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;インストールされている JetPack と OS のバージョンは以下の方法で確認できます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://senooken.jp/post/2020/12/04/" target="_blank" rel="noopener"
 &gt;https://senooken.jp/post/2020/12/04/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ dpkg-query --show nvidia-l4t-core
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nvidia-l4t-core 32.5.0-20210115151051
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;インストールされている OS は L4T 32.5 でしたが、これは JetPack 4.5 になるっぽいです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://developer.nvidia.com/embedded/jetpack-archive" target="_blank" rel="noopener"
 &gt;https://developer.nvidia.com/embedded/jetpack-archive&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;尚、最新の JetPack 4.6 でも CUDA は 10.2 らしいですが、これは GPU ドライバーの都合上みたいです（後述）。&lt;/p&gt;
&lt;h2 id="nvidia-smi-がない"&gt;&lt;a href="#nvidia-smi-%e3%81%8c%e3%81%aa%e3%81%84" class="header-anchor"&gt;&lt;/a&gt;nvidia-smi がない？
&lt;/h2&gt;&lt;p&gt;GPU の状況を確認するためによく使う &lt;code&gt;nvidia-smi&lt;/code&gt; が Jetson にはありませんでした。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://senooken.jp/post/2020/11/19/" target="_blank" rel="noopener"
 &gt;https://senooken.jp/post/2020/11/19/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;代わりに &lt;code&gt;tegrastats&lt;/code&gt; で確認できました。&lt;/p&gt;
&lt;h2 id="ストレージ容量が少ない"&gt;&lt;a href="#%e3%82%b9%e3%83%88%e3%83%ac%e3%83%bc%e3%82%b8%e5%ae%b9%e9%87%8f%e3%81%8c%e5%b0%91%e3%81%aa%e3%81%84" class="header-anchor"&gt;&lt;/a&gt;ストレージ容量が少ない
&lt;/h2&gt;&lt;p&gt;ストレージ容量が 16GB しかなく、空き容量もほとんどないので、このままでは Docker イメージが入りません。&lt;br&gt;
なので、外部ストレージとして 2.5 インチの SSD を用意して、そちらに Docker イメージを保存するように設定変更しました。&lt;br&gt;
これについては以下を参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/04/ubuntu-ssd.html" target="_blank" rel="noopener"
 &gt;Ubuntu に SSD をマウント&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/04/docker.html" target="_blank" rel="noopener"
 &gt;Docker イメージの保存先を変更&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="cuda-バージョン"&gt;&lt;a href="#cuda-%e3%83%90%e3%83%bc%e3%82%b8%e3%83%a7%e3%83%b3" class="header-anchor"&gt;&lt;/a&gt;CUDA バージョン
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;nvidia-container-cli&lt;/code&gt; が使えたので、何もしなくても Docker から GPU を使うことはできそうでした。&lt;br&gt;
インストールされている CUDA のバージョンなどは以下でした。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nvidia-container-cli info
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NVRM version: &lt;span class="o"&gt;(&lt;/span&gt;null&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CUDA version: 10.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Device Index: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Device Minor: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Model: Xavier
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Brand: &lt;span class="o"&gt;(&lt;/span&gt;null&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GPU UUID: &lt;span class="o"&gt;(&lt;/span&gt;null&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Bus Location: &lt;span class="o"&gt;(&lt;/span&gt;null&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Architecture: 7.2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;結構古かったです。&lt;/p&gt;
&lt;p&gt;んで、CUDA のバージョンを上げられないかなぁと思って調べてみると、以下のページが見つかりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://forums.developer.nvidia.com/t/manually-installing-cuda-11-0-2-on-jetson-xavier-nx-help/191909" target="_blank" rel="noopener"
 &gt;https://forums.developer.nvidia.com/t/manually-installing-cuda-11-0-2-on-jetson-xavier-nx-help/191909&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://forums.developer.nvidia.com/t/installing-cuda-11-x-on-jetson-nano/169109" target="_blank" rel="noopener"
 &gt;https://forums.developer.nvidia.com/t/installing-cuda-11-x-on-jetson-nano/169109&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;どうやら Jetson は GPU ドライバーの都合上、現時点では CUDA 11 以降に対応していないとのこと。&lt;br&gt;
なので、Dockerfile のイメージは CUDA 10.2 のものを使う必要がありそうです。&lt;/p&gt;
&lt;h2 id="cpu-が-arm"&gt;&lt;a href="#cpu-%e3%81%8c-arm" class="header-anchor"&gt;&lt;/a&gt;CPU が arm
&lt;/h2&gt;&lt;p&gt;CUDA 云々の前に、そもそも CPU アーキテクチャが arm なので、今まで他のマシンで使っていた Dockerfile のビルドを行うとすぐに失敗しました。&lt;br&gt;
ベースとする Docker イメージを arm 系のものにする必要がありそうです。&lt;/p&gt;
&lt;p&gt;Docker Hub に &lt;code&gt;nvidia/cuda-arm64&lt;/code&gt; というイメージがあるのでこれっぽいですが、現在ではもうサポートされておらず 11.1 でバージョンが止まっています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/r/nvidia/cuda-arm64" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/r/nvidia/cuda-arm64&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ドキュメントを追ってみると、現在では &lt;code&gt;nvidia/cuda&lt;/code&gt; のイメージで複数のアーキテクチャをサポートできるっぽいので、上記はもうサポートされないとのこと。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gitlab.com/nvidia/container-images/cuda/-/blob/master/README.md" target="_blank" rel="noopener"
 &gt;https://gitlab.com/nvidia/container-images/cuda/-/blob/master/README.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;しかし、&lt;code&gt;nvidia/cuda&lt;/code&gt; にある CUDA 10.2 のイメージの &lt;code&gt;OS/ARCH&lt;/code&gt; には &lt;code&gt;linux/arm64&lt;/code&gt; が含まれていません。
仕方ないので &lt;code&gt;nvidia/cuda-arm64&lt;/code&gt; 内で探してみますが、今度は CUDA 10.2 のイメージがなく、11 以降のイメージしかありません。&lt;/p&gt;
&lt;p&gt;つまり、Docker Hub にある NVIDIA の公式イメージには、arm アーキテクチャで CUDA が 10.2 のイメージがないということがわかりました。&lt;/p&gt;
&lt;h2 id="nvidia-gpu-cloud-ngc-のイメージを使えばいいらしい"&gt;&lt;a href="#nvidia-gpu-cloud-ngc-%e3%81%ae%e3%82%a4%e3%83%a1%e3%83%bc%e3%82%b8%e3%82%92%e4%bd%bf%e3%81%88%e3%81%b0%e3%81%84%e3%81%84%e3%82%89%e3%81%97%e3%81%84" class="header-anchor"&gt;&lt;/a&gt;NVIDIA GPU CLOUD (NGC) のイメージを使えばいいらしい
&lt;/h2&gt;&lt;p&gt;さてどうしたもんかと悩んでいたら、同じようなことを質問している人がいました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://forums.developer.nvidia.com/t/cuda-10-2-and-cublas10-deb-package-to-install-on-arm64-docker-container/177030" target="_blank" rel="noopener"
 &gt;https://forums.developer.nvidia.com/t/cuda-10-2-and-cublas10-deb-package-to-install-on-arm64-docker-container/177030&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これに対する回答として、&lt;code&gt;l4t-ml:r32.5.0-py3&lt;/code&gt; を使ってみてとのこと。&lt;br&gt;
このイメージは Docker Hub ではなく NVIDIA GPU CLOUD (NGC) からプルできるそうです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://catalog.ngc.nvidia.com/orgs/nvidia/containers/l4t-ml" target="_blank" rel="noopener"
 &gt;https://catalog.ngc.nvidia.com/orgs/nvidia/containers/l4t-ml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;見ての通り、これは JetPack 4.5 と同等の Docker イメージらしいです。&lt;br&gt;
ちなみに、Docker Hub からのプルではないため、イメージ名は以下のように指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker pull nvcr.io/nvidia/l4t-ml:r32.5.0-py3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一応プルできるところまでは確認できました。&lt;/p&gt;
&lt;h2 id="opencv-のインストールに失敗する"&gt;&lt;a href="#opencv-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%ab%e5%a4%b1%e6%95%97%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;OpenCV のインストールに失敗する
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;nvcr.io/nvidia/l4t-ml:r32.5.0-py3&lt;/code&gt; のイメージを使うことでようやく Dockerfile のビルドを開始できるところまで漕ぎ着けましたが、OpenCV のインストールに失敗しました。&lt;/p&gt;
&lt;p&gt;調べてみると以下のページが見つかりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://nisshingeppo.com/ai/jetson-opencv/" target="_blank" rel="noopener"
 &gt;https://nisshingeppo.com/ai/jetson-opencv/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;どうやら pip ではインストールできないようなので、ソースコードからビルドを行う必要がありそうですが、OpenCV に依存するライブラリも pip でインストールできなくなります。&lt;/p&gt;
&lt;p&gt;尚、Ubuntu 20.04 のベースイメージだと OpenCV のインストールは pip でできました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://senooken.jp/post/2020/11/19/" target="_blank" rel="noopener"
 &gt;https://senooken.jp/post/2020/11/19/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/tsutof/items/363e0f705bbcdc42f95c" target="_blank" rel="noopener"
 &gt;https://qiita.com/tsutof/items/363e0f705bbcdc42f95c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://nisshingeppo.com/ai/jetson-opencv/" target="_blank" rel="noopener"
 &gt;https://nisshingeppo.com/ai/jetson-opencv/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] Swarm を WebUI で管理できる Swarmpit を動かしてみる</title><link>https://blog.ponkotools.com/posts/2022/04/27/docker-swarmpit/</link><pubDate>Wed, 27 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/27/docker-swarmpit/</guid><description>&lt;p&gt;Docker Swarm モードにおけるクラスタ構成を Web で確認できる Swarmpit というのを知ったので、動かしてみました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;Docker 20.7&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="動かし方"&gt;&lt;a href="#%e5%8b%95%e3%81%8b%e3%81%97%e6%96%b9" class="header-anchor"&gt;&lt;/a&gt;動かし方
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/swarmpit/swarmpit" target="_blank" rel="noopener"
 &gt;GitHub&lt;/a&gt; に Swarm 用の &lt;code&gt;docker-compose.yml&lt;/code&gt; が公開されているので、クローンしてデプロイするだけで使えます。&lt;br&gt;
なので、Swarm モードが有効になっていることが前提となります。&lt;/p&gt;
&lt;p&gt;Swarm モードが有効になっていれば、以下のコマンドを実行するだけで OK です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git clone https://github.com/swarmpit/swarmpit -b master
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker stack deploy -c swarmpit/docker-compose.yml swarmpit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;特に何も変更することなく動きました。&lt;br&gt;
起動するまで結構時間がかかりました。&lt;/p&gt;
&lt;h2 id="ログイン"&gt;&lt;a href="#%e3%83%ad%e3%82%b0%e3%82%a4%e3%83%b3" class="header-anchor"&gt;&lt;/a&gt;ログイン
&lt;/h2&gt;&lt;p&gt;http://localhost:888/ にアクセスすると初期アカウントの設定画面が表示されます。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="268px" data-flex-grow="111" height="423" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/04/27/docker-swarmpit/01.webp" width="473"&gt;&lt;/p&gt;
&lt;p&gt;適当にアカウントを作成すると、以下のようにダッシュボードが表示されます。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="407px" data-flex-grow="169" height="721" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/04/27/docker-swarmpit/02.webp" srcset="https://blog.ponkotools.com/posts/2022/04/27/docker-swarmpit/02_hu_efed5127ec421201.webp 800w, https://blog.ponkotools.com/posts/2022/04/27/docker-swarmpit/02.webp 1224w" width="1224"&gt;&lt;/p&gt;
&lt;p&gt;Swarmpit 自身が４つのサービスからなるスタックで動作しているので、それが表示されているのが確認できます。&lt;/p&gt;
&lt;p&gt;まだ全然使っていませんが、気が向いたら使い方なども書いていこうかと思います。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/swarmpit/swarmpit" target="_blank" rel="noopener"
 &gt;https://github.com/swarmpit/swarmpit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] Image, Container, Node, Service, Stack などの概念</title><link>https://blog.ponkotools.com/posts/2022/04/26/docker/</link><pubDate>Tue, 26 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/26/docker/</guid><description>&lt;p&gt;Docker について、特に Swarm モードを使い始めるとここらへんの概念がややこしくなってきたので、整理してみました。&lt;/p&gt;
&lt;p&gt;ただ当ブログ全般に言えますが、私自身が正しく理解できているかどうかは自信がないので、あくまで参考ということで、内容の保証はいたしかねます。&lt;/p&gt;
&lt;h2 id="概念図"&gt;&lt;a href="#%e6%a6%82%e5%bf%b5%e5%9b%b3" class="header-anchor"&gt;&lt;/a&gt;概念図
&lt;/h2&gt;&lt;p&gt;以下のページの図がわかりやすかったです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://betterprogramming.pub/how-to-differentiate-between-docker-images-containers-stacks-machine-nodes-and-swarms-fd5f7e34eb9f" target="_blank" rel="noopener"
 &gt;https://betterprogramming.pub/how-to-differentiate-between-docker-images-containers-stacks-machine-nodes-and-swarms-fd5f7e34eb9f&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://babyron64.hatenablog.com/entry/2017/11/14/193242" target="_blank" rel="noopener"
 &gt;https://babyron64.hatenablog.com/entry/2017/11/14/193242&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これを踏まえつつ、とりあえず簡単に理解するためには以下のような感じでよいのかなと思います。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="375px" data-flex-grow="156" height="301" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/04/26/docker/01.webp" width="471"&gt;&lt;/p&gt;
&lt;h2 id="docker-イメージ"&gt;&lt;a href="#docker-%e3%82%a4%e3%83%a1%e3%83%bc%e3%82%b8" class="header-anchor"&gt;&lt;/a&gt;Docker イメージ
&lt;/h2&gt;&lt;p&gt;イメージは、アプリケーションのコード、ランタイム、ライブラリ、環境変数、構成ファイルなど、アプリケーションの実行に必要なすべてのものを含んだ、実行可能パッケージです。&lt;br&gt;
このイメージを動作させるためにインスタンス化したものがコンテナと言えます。&lt;/p&gt;
&lt;h2 id="docker-コンテナ"&gt;&lt;a href="#docker-%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a" class="header-anchor"&gt;&lt;/a&gt;Docker コンテナ
&lt;/h2&gt;&lt;p&gt;コンテナは Docker における最小の動作単位です。&lt;br&gt;
コンテナはイメージから作成されます。&lt;br&gt;
上述のページでは、コンテナはイメージのランタイムインスタンスである、という言い方をしていますが、イメージを実際に動作可能にしたものがコンテナである、と言ってもいいかもしれません。&lt;/p&gt;
&lt;p&gt;コンテナを動作させると、ホストからは一つのプロセスとして認識されます。&lt;br&gt;
カーネルはホストと共有しています。&lt;/p&gt;
&lt;p&gt;尚、イメージおよびコンテナはレイヤー構造となっており、各レイヤーはベースレイヤーとの差分情報を持っています。&lt;br&gt;
ここらへん、以下のページがわかりやすかったです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/okmtz/items/f8231c83134a6363647b" target="_blank" rel="noopener"
 &gt;https://qiita.com/okmtz/items/f8231c83134a6363647b&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、コンテナ内で動かすアプリケーションは１つにするのが基本だそうです。&lt;br&gt;
理由などは以下を見ていただくのが早いです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://matsuand.github.io/docs.docker.jp.onthefly/get-started/07_multi_container/" target="_blank" rel="noopener"
 &gt;https://matsuand.github.io/docs.docker.jp.onthefly/get-started/07_multi_container/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="データボリューム"&gt;&lt;a href="#%e3%83%87%e3%83%bc%e3%82%bf%e3%83%9c%e3%83%aa%e3%83%a5%e3%83%bc%e3%83%a0" class="header-anchor"&gt;&lt;/a&gt;データボリューム
&lt;/h2&gt;&lt;p&gt;コンテナ内にデータを保存した場合、コンテナの破棄とともにそのデータも消えてしまいます。&lt;br&gt;
そのため、データが消えてしまわないように永続化する際に使うのがデータボリュームです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.jp/engine/userguide/dockervolumes.html" target="_blank" rel="noopener"
 &gt;https://docs.docker.jp/engine/userguide/dockervolumes.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;データボリュームはコンテナ内の指定したパスにマウントして使います。&lt;/p&gt;
&lt;h2 id="docker-compose"&gt;&lt;a href="#docker-compose" class="header-anchor"&gt;&lt;/a&gt;docker-compose
&lt;/h2&gt;&lt;p&gt;前述したとおり、Docker では１つのコンテナで１つのアプリケーションを動かすのが基本です。&lt;br&gt;
しかし、実際のシステムでは複数のアプリケーションが連携して動作するものが多いと思います。&lt;br&gt;
そういった複数のコンテナ（アプリケーション）が連携して動作するシステムについて、イメージのビルドや依存関係を考慮して各コンテナの起動・停止などを簡単に行えるようにできるツールが docker-compose です。&lt;/p&gt;
&lt;h2 id="swarm-モード"&gt;&lt;a href="#swarm-%e3%83%a2%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;Swarm モード
&lt;/h2&gt;&lt;p&gt;Swarm モードは Docker 自体に含まれるオーケストレーション機能です。&lt;br&gt;
複数の Docker ホストをまとめて、クラスタを構成することができます。&lt;/p&gt;
&lt;h2 id="ノード"&gt;&lt;a href="#%e3%83%8e%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;ノード
&lt;/h2&gt;&lt;p&gt;ノードは Swarm モードによるクラスタを構成する単位で、Docker ホスト１つにつきノードを１つ作成することになります。&lt;/p&gt;
&lt;p&gt;例えば、２つの物理マシン上でそれぞれ Docker を使っている場合は、各マシンにノードを作成してクラスタを構成します。&lt;br&gt;
ただし、VirtualBox や WSL などの仮想環境を使うと一つの物理マシン上で複数の Docker ホストが存在することもあるので、必ずしも「ノードの数＝マシンの数」となるわけではありません。&lt;/p&gt;
&lt;p&gt;尚、ノードにはクラスタ全体を管理する manager ノードと、コンテナを実行する worker ノードがあります。&lt;/p&gt;
&lt;h2 id="サービスとタスク"&gt;&lt;a href="#%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%81%a8%e3%82%bf%e3%82%b9%e3%82%af" class="header-anchor"&gt;&lt;/a&gt;サービスとタスク
&lt;/h2&gt;&lt;p&gt;Swarm モードにおいて、ノードの作成の次はサービスの作成を行います。
サービスを作成すると、タスク（コンテナ）が作成されて、各ノードに配置されます。
タスクというのはコンテナを起動したりするやつで、よくわからなければ基本的にタスク≒コンテナと考えてよさそうです。&lt;/p&gt;
&lt;p&gt;つまり、サービスを作成するとは、同じ機能を持ったタスク（コンテナ）を複数作成して（レプリカセット）、各ノードに配置するということになります。
この各ノードに配置されたタスク（コンテナ）のレプリカセットがサービスです。&lt;/p&gt;
&lt;p&gt;非 Swarm モードにおけるコンテナ作成（つまり普通にコンテナを作成する場合）が、Swarm モード有効時ではサービスを作成することに相当する、と考えればわかりやすいかもしれません。&lt;/p&gt;
&lt;p&gt;従って、１つのコンテナでは基本的に１つのアプリケーションしか動いていないのと同様に、１つサービスでは基本的に１つの機能しか持っていません。&lt;br&gt;
レプリカがあるためタスク（コンテナ）自体は複数ありますがが（冗長化）、機能としてはタスク（コンテナ）１つ分しかありません。&lt;br&gt;
そのため、複数のサービスが連携して動作するシステムの場合、次のスタックを使うことになります。&lt;/p&gt;
&lt;h2 id="スタック"&gt;&lt;a href="#%e3%82%b9%e3%82%bf%e3%83%83%e3%82%af" class="header-anchor"&gt;&lt;/a&gt;スタック
&lt;/h2&gt;&lt;p&gt;サービスの集合体がスタックです。&lt;br&gt;
非 Swarm モードで依存関係のあるコンテナを一度に起動・終了したりする場合、前述したように docker-compose を使ったりしますが、これが Swarm モードではスタックに相当します。
非 Swarm モードにおける コンテナと docker-compose の関係が、Swarm モードではサービスとスタックの関係になる、といえばわかりやすいかもしれません。&lt;/p&gt;
&lt;p&gt;スタックでは基本的に &lt;code&gt;docker-compose.yml&lt;/code&gt; がそのまま使えますが、一部使えない項目や、逆に必要となる項目などもあるので、こちらはまた別途記事を作成したいと思います。&lt;/p&gt;
&lt;h2 id="オーバーレイネットワーク"&gt;&lt;a href="#%e3%82%aa%e3%83%bc%e3%83%90%e3%83%bc%e3%83%ac%e3%82%a4%e3%83%8d%e3%83%83%e3%83%88%e3%83%af%e3%83%bc%e3%82%af" class="header-anchor"&gt;&lt;/a&gt;オーバーレイネットワーク
&lt;/h2&gt;&lt;p&gt;Swarm モードでは、Docker ホスト間を相互接続するために、オーバーレイネットワークが作成されます。&lt;br&gt;
デフォルトで Ingress という名前のオーバーレイネットワークが作成されます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://matsuand.github.io/docs.docker.jp.onthefly/network/overlay/" target="_blank" rel="noopener"
 &gt;https://matsuand.github.io/docs.docker.jp.onthefly/network/overlay/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://blog.livedoor.jp/harukisan7/archives/17495300.html" target="_blank" rel="noopener"
 &gt;http://blog.livedoor.jp/harukisan7/archives/17495300.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://betterprogramming.pub/how-to-differentiate-between-docker-images-containers-stacks-machine-nodes-and-swarms-fd5f7e34eb9f" target="_blank" rel="noopener"
 &gt;https://betterprogramming.pub/how-to-differentiate-between-docker-images-containers-stacks-machine-nodes-and-swarms-fd5f7e34eb9f&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://babyron64.hatenablog.com/entry/2017/11/14/193242" target="_blank" rel="noopener"
 &gt;https://babyron64.hatenablog.com/entry/2017/11/14/193242&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Jetson Xavier NX でルートファイルシステムを overlayroot で読み込み専用に設定する</title><link>https://blog.ponkotools.com/posts/2022/04/26/jetson-overlayroot/</link><pubDate>Tue, 26 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/26/jetson-overlayroot/</guid><description>&lt;p&gt;以前、Ubuntu で overlayroot を使ってルートファイルシステムを読み込み専用にしてみたのですが、Jetson Xavier NX で同じように試してみたところ、それだけではだめでした。&lt;/p&gt;
&lt;p&gt;恐らくですが、ブートローダーが EXTLINUX であることが原因のような気がしています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide/uboot_guide.html#wwpID0E0YD0HA" target="_blank" rel="noopener"
 &gt;https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide/uboot_guide.html#wwpID0E0YD0HA&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Jetson Xavier NX ではどうやってやればいいのかググってみると、NVIDIA のフォーラムで議論されているのが見つかりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://forums.developer.nvidia.com/t/xavier-nx-filesystem-to-readonly/185605" target="_blank" rel="noopener"
 &gt;https://forums.developer.nvidia.com/t/xavier-nx-filesystem-to-readonly/185605&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://forums.developer.nvidia.com/t/overlayfs-for-jetson/78540/29" target="_blank" rel="noopener"
 &gt;https://forums.developer.nvidia.com/t/overlayfs-for-jetson/78540/29&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;その中で、解決策として提示されていたのが以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/negachov/overlayroot-jetpack" target="_blank" rel="noopener"
 &gt;https://github.com/negachov/overlayroot-jetpack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Jetson Xavior NX&lt;/li&gt;
&lt;li&gt;Ubuntu 18.04&lt;/li&gt;
&lt;li&gt;JetPack 4.5.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="overlayroot-のインストールと有効化"&gt;&lt;a href="#overlayroot-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%a8%e6%9c%89%e5%8a%b9%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;overlayroot のインストールと有効化
&lt;/h2&gt;&lt;p&gt;以下の記事を参考にしてください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/04/overlayroot-ubuntu.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/04/overlayroot-ubuntu.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Jetson Xavier NX ではこれに加え、次のことが必要でした。&lt;/p&gt;
&lt;h2 id="bootinitrd-の置き換え"&gt;&lt;a href="#bootinitrd-%e3%81%ae%e7%bd%ae%e3%81%8d%e6%8f%9b%e3%81%88" class="header-anchor"&gt;&lt;/a&gt;/boot/initrd の置き換え
&lt;/h2&gt;&lt;p&gt;GitHub にスクリプトが公開されているので、まずこれをクローンします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git clone https://github.com/negachov/overlayroot-jetpack
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとは以下を実行するだけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; overlayroot-jetpack
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo ./update-initramfs-jetpack
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ reboot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで、再起動後に overlayroot が有効になっていました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://forums.developer.nvidia.com/t/xavier-nx-filesystem-to-readonly/185605" target="_blank" rel="noopener"
 &gt;https://forums.developer.nvidia.com/t/xavier-nx-filesystem-to-readonly/185605&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://forums.developer.nvidia.com/t/overlayfs-for-jetson/78540/29" target="_blank" rel="noopener"
 &gt;https://forums.developer.nvidia.com/t/overlayfs-for-jetson/78540/29&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.nvidia.com/jetson/l4t/Tegra%20Linux%20Driver%20Package%20Development%20Guide/uboot_guide.html#wwpID0E0YD0HA" target="_blank" rel="noopener"
 &gt;https://docs.nvidia.com/jetson/l4t/Tegra%20Linux%20Driver%20Package%20Development%20Guide/uboot_guide.html#wwpID0E0YD0HA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://zenn.dev/tunefs/articles/288d3a069f0cb3" target="_blank" rel="noopener"
 &gt;https://zenn.dev/tunefs/articles/288d3a069f0cb3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Ubuntu のファイルシステムを overlayroot で読み込み専用にする</title><link>https://blog.ponkotools.com/posts/2022/04/25/overlayroot/</link><pubDate>Mon, 25 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/25/overlayroot/</guid><description>&lt;p&gt;電源ブチ切り対策の一環として、overlayroot で Ubuntu の rootfs を read only にしてみました。&lt;/p&gt;
&lt;p&gt;やり方はいろいろググってみましたが、以下のサイトがとても参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gihyo.jp/admin/serial/01/ubuntu-recipe/0568" target="_blank" rel="noopener"
 &gt;https://gihyo.jp/admin/serial/01/ubuntu-recipe/0568&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://zenn.dev/tunefs/articles/288d3a069f0cb3" target="_blank" rel="noopener"
 &gt;https://zenn.dev/tunefs/articles/288d3a069f0cb3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04 (デスクトップ版)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="現在の状態を確認"&gt;&lt;a href="#%e7%8f%be%e5%9c%a8%e3%81%ae%e7%8a%b6%e6%85%8b%e3%82%92%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;現在の状態を確認
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;mount&lt;/code&gt; コマンドで確認してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mount
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;抜粋ですが、以下の状態が確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/dev/sda2 on / &lt;span class="nb"&gt;type&lt;/span&gt; ext4 &lt;span class="o"&gt;(&lt;/span&gt;rw,relatime,errors&lt;span class="o"&gt;=&lt;/span&gt;remount-ro&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="overlayroot-のインストール"&gt;&lt;a href="#overlayroot-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;overlayroot のインストール
&lt;/h2&gt;&lt;p&gt;サーバー版には最初からインストールされているそうですが、デスクトップ版にはインストールされていないので、apt でインストールします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install overlayroot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="overlayroot-の有効化"&gt;&lt;a href="#overlayroot-%e3%81%ae%e6%9c%89%e5%8a%b9%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;overlayroot の有効化
&lt;/h2&gt;&lt;p&gt;overlayroot を有効化するには、以下のいずれかの対応が必要だそうです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;カーネルパラメーターに &lt;code&gt;overlayroot=XXX&lt;/code&gt; を指定する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/etc/overlayroot.local.conf&lt;/code&gt; に &lt;code&gt;overlayroot=&amp;quot;XXX&amp;quot;&lt;/code&gt; を指定する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/etc/overlayroot.conf&lt;/code&gt; に &lt;code&gt;overlayroot=&amp;quot;XXX&amp;quot;&lt;/code&gt; を指定する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;設定内容は上位のほうが優先されるそうです。&lt;br&gt;
今回は &lt;code&gt;/etc/overlayroot.local.conf&lt;/code&gt; に設定を追加します。&lt;br&gt;
まずはエディタで開きます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo gedit /etc/overlayroot.local.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;overlayroot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tmpfs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コマンド一発でやるなら以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;overlayroot=&amp;#34;tmpfs&amp;#34;&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee -a /etc/overlayroot.local.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;tmpfs はメモリ上に作成ファイルシステムで、一時的にデータを格納するために使われます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://linuc.org/study/knowledge/441/" target="_blank" rel="noopener"
 &gt;https://linuc.org/study/knowledge/441/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Linux ではマウントするファイルシステムの情報が &lt;code&gt;/etc/fstab&lt;/code&gt; に書かれていますが、ここが overlayroot における下位レイヤーとなり、読み込み専用レイヤーとなります。&lt;br&gt;
そして、先ほど追記した &lt;code&gt;tempfs&lt;/code&gt; が上位レイヤーとなり、書き込み可能レイヤーとなります。&lt;br&gt;
ここらへんは後述するように &lt;code&gt;mount&lt;/code&gt; コマンドで確認可能です。&lt;/p&gt;
&lt;p&gt;ただし、tmpfs はメモリ上に作成されたファイルシステムなので、再起動時にはデータは消えます。&lt;/p&gt;
&lt;h3 id="ルートファイルシステムのみを読み取り専用にする"&gt;&lt;a href="#%e3%83%ab%e3%83%bc%e3%83%88%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%82%b7%e3%82%b9%e3%83%86%e3%83%a0%e3%81%ae%e3%81%bf%e3%82%92%e8%aa%ad%e3%81%bf%e5%8f%96%e3%82%8a%e5%b0%82%e7%94%a8%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;ルートファイルシステムのみを読み取り専用にする
&lt;/h3&gt;&lt;p&gt;パーティションを分けている場合などで、ルートファイルシステムのみを読み取り専用にするためには、&lt;code&gt;/etc/overlayroot.local.conf&lt;/code&gt; に &lt;code&gt;tmpfs:recurse=0&lt;/code&gt; を指定するらしいです。&lt;br&gt;
コマンド一発でやる場合は以下。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gihyo.jp/admin/serial/01/ubuntu-recipe/0568" target="_blank" rel="noopener"
 &gt;https://gihyo.jp/admin/serial/01/ubuntu-recipe/0568&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;echo &amp;#39;overlayroot=&amp;#34;tmpfs:recurse=0&amp;#34;&amp;#39; | sudo tee -a /etc/overlayroot.local.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで再起動すれば、ルートファイルシステムのみが読み取り専用となり、他のパーティションは読み書き可能な状態となります。&lt;/p&gt;
&lt;h2 id="確認"&gt;&lt;a href="#%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;確認
&lt;/h2&gt;&lt;p&gt;先ほどと同じように &lt;code&gt;mount&lt;/code&gt; コマンドで確認してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mount
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;抜粋ですが、以下の状態が確認できました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/dev/sda2 on /media/root-ro &lt;span class="nb"&gt;type&lt;/span&gt; ext4 &lt;span class="o"&gt;(&lt;/span&gt;ro,relatime&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tmpfs-root on /media/root-rw &lt;span class="nb"&gt;type&lt;/span&gt; tmpfs &lt;span class="o"&gt;(&lt;/span&gt;rw,relatime,inode64&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;overlayroot on / &lt;span class="nb"&gt;type&lt;/span&gt; overlay &lt;span class="o"&gt;(&lt;/span&gt;rw,relatime,lowerdir&lt;span class="o"&gt;=&lt;/span&gt;/media/root-ro,upperdir&lt;span class="o"&gt;=&lt;/span&gt;/media/root-rw/overlay,workdir&lt;span class="o"&gt;=&lt;/span&gt;/media/root-rw/overlay-workdir/_&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ルートファイルシステムが &lt;code&gt;/media/root-ro&lt;/code&gt; に読み込み専用(ro)の下位レイヤー(lowerdir) として設定され、tmpfs が &lt;code&gt;/media/root-rw/overlay&lt;/code&gt; に書き込み可能(rw)な上位レイヤー(upperdir) して設定されているのが確認できます。&lt;/p&gt;
&lt;h3 id="ファイルが消えることを確認"&gt;&lt;a href="#%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%8c%e6%b6%88%e3%81%88%e3%82%8b%e3%81%93%e3%81%a8%e3%82%92%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;ファイルが消えることを確認
&lt;/h3&gt;&lt;p&gt;ついでに、ホームディレクトリに適当にファイルを作成し、再起動時にファイルが消えていることを確認します。&lt;/p&gt;
&lt;h2 id="overlayroot-の無効化"&gt;&lt;a href="#overlayroot-%e3%81%ae%e7%84%a1%e5%8a%b9%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;overlayroot の無効化
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;/etc/overlayroot.local.conf&lt;/code&gt; を削除するか、&lt;code&gt;/etc/overlayroot.local.conf&lt;/code&gt; を編集して中身を &lt;code&gt;overlayroot=&amp;quot;&amp;quot;&lt;/code&gt; に変更すれば、overlayroot の無効化されます。&lt;/p&gt;
&lt;p&gt;しかし、現在は overlayroot が有効化になっている状況なので、このまま変更しても再起動後にはまた元に戻ってしまいます。&lt;br&gt;
そのため、この変更は一時的に書き込みを許可した状態で行う必要があります。&lt;br&gt;
一時的に書き込み可能な状態にするには以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo overlayroot-chroot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そして、&lt;code&gt;/etc/overlayroot.local.conf&lt;/code&gt; を削除するか、&lt;code&gt;/etc/overlayroot.local.conf&lt;/code&gt; を編集して中身を &lt;code&gt;overlayroot=&amp;quot;&amp;quot;&lt;/code&gt; に変更します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# rm /etc/overlayroot.local.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;exit&lt;/code&gt; でシェルから抜ければ書き込み可能状態は終了します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再起動後、overlayroot が無効状態になっています。&lt;/p&gt;
&lt;h2 id="grub-メニューで時間がかかることの対策"&gt;&lt;a href="#grub-%e3%83%a1%e3%83%8b%e3%83%a5%e3%83%bc%e3%81%a7%e6%99%82%e9%96%93%e3%81%8c%e3%81%8b%e3%81%8b%e3%82%8b%e3%81%93%e3%81%a8%e3%81%ae%e5%af%be%e7%ad%96" class="header-anchor"&gt;&lt;/a&gt;GRUB メニューで時間がかかることの対策
&lt;/h2&gt;&lt;p&gt;overlayroot を有効にした状態で再起動すると、GRUB メニューが表示され、30秒ほど待たされるようになります。&lt;br&gt;
詳細は以下をご参照ください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gihyo.jp/admin/serial/01/ubuntu-recipe/0568" target="_blank" rel="noopener"
 &gt;https://gihyo.jp/admin/serial/01/ubuntu-recipe/0568&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;起動が30秒も遅くなるのは困るので、以下を参考にして GRUB の設定を変更しました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://askubuntu.com/questions/754974/grub-defaulting-to-30-second-timeout" target="_blank" rel="noopener"
 &gt;https://askubuntu.com/questions/754974/grub-defaulting-to-30-second-timeout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://plaza.rakuten.co.jp/ftechworks/diary/202005130001/" target="_blank" rel="noopener"
 &gt;https://plaza.rakuten.co.jp/ftechworks/diary/202005130001/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.hiroom2.com/2018/04/30/ubuntu-1804-serial-console-ja/" target="_blank" rel="noopener"
 &gt;https://www.hiroom2.com/2018/04/30/ubuntu-1804-serial-console-ja/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;※以下は overlayroot を無効にした状態で行う必要があります！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/etc/default/grub&lt;/code&gt; をエディタで開きます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo nano /etc/default/grub
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GRUB_RECORDFAIL_TIMEOUT=$GRUB_TIMEOUT
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;設定を反映するために以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo grub-mkconfig -o /boot/grub/grub.cfg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで overlayroot を有効にしても起動時間は変わらなくなりました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gihyo.jp/admin/serial/01/ubuntu-recipe/0568" target="_blank" rel="noopener"
 &gt;https://gihyo.jp/admin/serial/01/ubuntu-recipe/0568&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://askubuntu.com/questions/754974/grub-defaulting-to-30-second-timeout" target="_blank" rel="noopener"
 &gt;https://askubuntu.com/questions/754974/grub-defaulting-to-30-second-timeout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://plaza.rakuten.co.jp/ftechworks/diary/202005130001/" target="_blank" rel="noopener"
 &gt;https://plaza.rakuten.co.jp/ftechworks/diary/202005130001/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.hiroom2.com/2018/04/30/ubuntu-1804-serial-console-ja/" target="_blank" rel="noopener"
 &gt;https://www.hiroom2.com/2018/04/30/ubuntu-1804-serial-console-ja/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] Swarm モードのローリングアップデートを試してみた</title><link>https://blog.ponkotools.com/posts/2022/04/24/docker-swarm/</link><pubDate>Sun, 24 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/24/docker-swarm/</guid><description>&lt;p&gt;Docker Swarm のチュートリアルの続きで、ローリングアップデートを試してみました。&lt;/p&gt;
&lt;p&gt;前回の記事は以下。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/04/docker-swarm_22.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/04/docker-swarm_22.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="準備"&gt;&lt;a href="#%e6%ba%96%e5%82%99" class="header-anchor"&gt;&lt;/a&gt;準備
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;redis:3.0.6&lt;/code&gt; のイメージでサービスを開始します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service create --replicas &lt;span class="m"&gt;3&lt;/span&gt; --name redis --update-delay 10s redis:3.0.6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;zzbrzxvmf40nt9jj8dw0upfqf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;overall progress: &lt;span class="m"&gt;3&lt;/span&gt; out of &lt;span class="m"&gt;3&lt;/span&gt; tasks 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1/3: running &lt;span class="o"&gt;[==================================================&lt;/span&gt;&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2/3: running &lt;span class="o"&gt;[==================================================&lt;/span&gt;&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3/3: running &lt;span class="o"&gt;[==================================================&lt;/span&gt;&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;verify: Service converged 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;--replicas 3&lt;/code&gt; を指定しているので、タスク（コンテナ）が３つ作成されます。&lt;/p&gt;
&lt;p&gt;これを今から &lt;code&gt;redis:3.0.7&lt;/code&gt; のイメージを使うようにアップデートします。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--update-parallelism&lt;/code&gt; で同時に更新するタスクの数を指定できるようですが、今回は指定していないので、１つずつ更新されていきます。&lt;br&gt;
また、&lt;code&gt;--update-delay 10s&lt;/code&gt; を指定しているので、各タスクの更新は10秒の間隔を空けて行われます。&lt;/p&gt;
&lt;h3 id="確認"&gt;&lt;a href="#%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;確認
&lt;/h3&gt;&lt;p&gt;アップデートの前に先に現状を確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service inspect --pretty redis
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID:		zzbrzxvmf40nt9jj8dw0upfqf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name:		redis
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Service Mode:	Replicated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Replicas:	&lt;span class="m"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Placement:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;UpdateConfig:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Parallelism:	&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Delay:		10s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; On failure:	pause
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Monitoring Period: 5s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Max failure ratio: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Update order: stop-first
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RollbackConfig:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Parallelism:	&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; On failure:	pause
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Monitoring Period: 5s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Max failure ratio: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Rollback order: stop-first
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ContainerSpec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image:		redis:3.0.6@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Init:		&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Resources:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Endpoint Mode:	vip
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下はチュートリアルにはありませんが、もう少しサービスの状況を確認しておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME MODE REPLICAS IMAGE PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;zzbrzxvmf40n redis replicated 3/3 redis:3.0.6 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service ps redis
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;78sw528i15lh redis.1 redis:3.0.6 worker1 Running Running &lt;span class="m"&gt;2&lt;/span&gt; minutes ago 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ryj86p3my9v4 redis.2 redis:3.0.6 manager1 Running Running about a minute ago 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cwoso93243ra redis.3 redis:3.0.6 worker1 Running Running &lt;span class="m"&gt;2&lt;/span&gt; minutes ago 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;redis&lt;/code&gt; というサービスが２つのノード上で合計３つ動作しているのが確認できます。&lt;/p&gt;
&lt;h2 id="アップデート"&gt;&lt;a href="#%e3%82%a2%e3%83%83%e3%83%97%e3%83%87%e3%83%bc%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;アップデート
&lt;/h2&gt;&lt;p&gt;以下のコマンドで、&lt;code&gt;redis:3.0.7&lt;/code&gt; にアップデートを開始します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service update --image redis:3.0.7 redis
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;別の端末で &lt;code&gt;docker service ps&lt;/code&gt; を実行すれば、タスク（コンテナ）が順にアップデートされていくのが確認できます。&lt;/p&gt;
&lt;h3 id="確認-1"&gt;&lt;a href="#%e7%a2%ba%e8%aa%8d-1" class="header-anchor"&gt;&lt;/a&gt;確認
&lt;/h3&gt;&lt;p&gt;アップデートが全て完了したら、以下のように各タスク（コンテナ）が &lt;code&gt;redis:3.0.6&lt;/code&gt; から &lt;code&gt;redis:3.0.7&lt;/code&gt; にアップデートされているのが確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service ps redis
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;9zedj7hcwbsk redis.1 redis:3.0.7 manager1 Running Running &lt;span class="m"&gt;12&lt;/span&gt; seconds ago 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yy3ov31879rx &lt;span class="se"&gt;\_&lt;/span&gt; redis.1 redis:3.0.6 manager1 Shutdown Shutdown &lt;span class="m"&gt;13&lt;/span&gt; seconds ago 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fize7rde390v redis.2 redis:3.0.7 worker1 Running Running &lt;span class="m"&gt;59&lt;/span&gt; seconds ago 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tn49red4crkq &lt;span class="se"&gt;\_&lt;/span&gt; redis.2 redis:3.0.6 worker1 Shutdown Shutdown about a minute ago 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;os380kdgnmfg redis.3 redis:3.0.7 manager1 Running Running &lt;span class="m"&gt;37&lt;/span&gt; seconds ago 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3scdfazrhn6z &lt;span class="se"&gt;\_&lt;/span&gt; redis.3 redis:3.0.6 Pworker1 Shutdown Shutdown about a minute ago
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="アップデートに失敗した場合"&gt;&lt;a href="#%e3%82%a2%e3%83%83%e3%83%97%e3%83%87%e3%83%bc%e3%83%88%e3%81%ab%e5%a4%b1%e6%95%97%e3%81%97%e3%81%9f%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;アップデートに失敗した場合
&lt;/h3&gt;&lt;p&gt;アップデートに失敗した場合は処理が一時停止状態になるようです。&lt;br&gt;
&lt;code&gt;docker service inspect&lt;/code&gt; でアップデートの状況を確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service inspect --pretty redis
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一時停止した更新を再開するには、 &lt;code&gt;docker service update &amp;lt;サービス ID&amp;gt;&lt;/code&gt; を実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service update redis
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/Brutus/items/99f59eefca4ff9ebb79e#%E3%83%93%E3%83%AB%E3%83%89%E4%BD%9C%E6%A5%AD" target="_blank" rel="noopener"
 &gt;https://qiita.com/Brutus/items/99f59eefca4ff9ebb79e#%E3%83%93%E3%83%AB%E3%83%89%E4%BD%9C%E6%A5%AD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/kiida/items/6dac109dcd063609b064" target="_blank" rel="noopener"
 &gt;https://qiita.com/kiida/items/6dac109dcd063609b064&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] Swarm モードに入門してみた</title><link>https://blog.ponkotools.com/posts/2022/04/22/docker-swarm/</link><pubDate>Fri, 22 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/22/docker-swarm/</guid><description>&lt;p&gt;Docker をプロダクションで使っていくにあたり、コンテナの管理やアップデートをどうしようかと考えていました。&lt;br&gt;
最初はこれを機に Kubernetes を使ってみようかと思ったのですが、学習コストが高いうえに、対象が小さなシステムなのでちょっと大仰すぎるなぁと思ってたところ、Docker 自体に Swarm モードというオーケストレーション機能が含まれていることを知ったので、そちらを試しに使ってみることにしました。&lt;/p&gt;
&lt;p&gt;というわけで、以下のチュートリアルを少しやってみました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://docs.docker.jp/engine/swarm/swarm-tutorial/toc.html" target="_blank" rel="noopener"
 &gt;http://docs.docker.jp/engine/swarm/swarm-tutorial/toc.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;手順としては上記をなぞるだけになるかもしれませんが、自分にとってわかりにくかったところや、他のサイトで調べたりしたことなどを補足しながら書いていこうと思います。&lt;br&gt;
一応、Swarm のドキュメントは以下になります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://docs.docker.jp/engine/swarm/toc.html" target="_blank" rel="noopener"
 &gt;http://docs.docker.jp/engine/swarm/toc.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ちなみに Kubernetes と Docker Swarm の比較は以下のページがとても参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://circleci.com/ja/blog/docker-swarm-vs-kubernetes/" target="_blank" rel="noopener"
 &gt;https://circleci.com/ja/blog/docker-swarm-vs-kubernetes/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04
&lt;ul&gt;
&lt;li&gt;Docker 20.10.7&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ubuntu 20.04 on WSL2 on Windows10
&lt;ul&gt;
&lt;li&gt;Docker 20.10.10&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Docker はインストール済みの前提です。&lt;br&gt;
Docker がインストールされていれば Swarm モードも使えます。&lt;/p&gt;
&lt;p&gt;チュートリアルでは Docker ホストは３つありますが、用意できなかったので Ubuntu と WSL2 上の Ubuntu の２つでやりました。&lt;/p&gt;
&lt;h2 id="概要"&gt;&lt;a href="#%e6%a6%82%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;概要
&lt;/h2&gt;&lt;p&gt;Docker Swarm モードは &lt;code&gt;manager&lt;/code&gt; ノードと &lt;code&gt;worker&lt;/code&gt; ノードから構成されます。&lt;br&gt;
ノードというのは Docker のホスト（Docker エンジンが動作している環境）の単位になります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;manager ノードはクラスタを管理するノード&lt;/li&gt;
&lt;li&gt;worker ノードはコンテナを稼働させるノード&lt;/li&gt;
&lt;li&gt;manager ノードは worker ノードを兼ねることもできる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="swarm-モードの有効化"&gt;&lt;a href="#swarm-%e3%83%a2%e3%83%bc%e3%83%89%e3%81%ae%e6%9c%89%e5%8a%b9%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;Swarm モードの有効化
&lt;/h2&gt;&lt;p&gt;Swarm モードを有効化するには &lt;code&gt;docker swarm init&lt;/code&gt; を実行します。&lt;br&gt;
このコマンドを実行すると manager ノードが作成されるので、manager ノードを作成したいマシン上で実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker swarm init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Swarm initialized: current node &lt;span class="o"&gt;(&lt;/span&gt;z9voajpw84i4jk2fomqwsmnc7&lt;span class="o"&gt;)&lt;/span&gt; is now a manager.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To add a worker to this swarm, run the following command:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; docker swarm join --token SWMTKN-1-23t6ldii7xxyyol2ulu0qddlqgwp3i1xpckiij2yjpintebbjq-bw598idhl229sykrhyiykviiw 192.168.1.10:2377
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To add a manager to this swarm, run &lt;span class="s1"&gt;&amp;#39;docker swarm join-token manager&amp;#39;&lt;/span&gt; and follow the instructions.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;出力結果には worker ノードを manager ノードに登録するためのコマンドが表示されます（後述）。&lt;/p&gt;
&lt;p&gt;また、１つのマシンに複数のIPアドレスが割り当てられている場合、以下のように &lt;code&gt;--advertise-addr&lt;/code&gt; オプションで他のノードとの通信に使用するIPアドレスを指定することもできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker swarm init --advertise-addr 192.168.1.10
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="確認"&gt;&lt;a href="#%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;確認
&lt;/h3&gt;&lt;p&gt;Swarm モードが有効になっているかどうかは &lt;code&gt;docker info&lt;/code&gt; で確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker info
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;抜粋ですが、以下のような出力が確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Swarm: active
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; NodeID: z9voajpw84i4jk2fomqwsmnc7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Is Manager: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ClusterID: 61lmt9ptc8jyphn725cj96vxj
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Managers: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Nodes: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ノードに関する情報は &lt;code&gt;docker node ls&lt;/code&gt; で確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker node ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;z9voajpw84i4jk2fomqwsmnc7 * manager1 Ready Active Leader 20.10.7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="worker-ノードの作成"&gt;&lt;a href="#worker-%e3%83%8e%e3%83%bc%e3%83%89%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;worker ノードの作成
&lt;/h2&gt;&lt;p&gt;worker ノードの作成には &lt;code&gt;docker swarm init&lt;/code&gt; を実行したときの出力結果に表示されたコマンドを使います。&lt;br&gt;
manager ノードを作成したマシンとは別のマシンで以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker swarm join --token SWMTKN-1-23t6ldii7xxyyol2ulu0qddlqgwp3i1xpckiij2yjpintebbjq-bw598idhl229sykrhyiykviiw 192.168.1.10:2377
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;This node joined a swarm as a worker.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;もし上記のコマンドが分からない場合は、&lt;code&gt;docker swarm join-token worker&lt;/code&gt; で確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker swarm join-token worker
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;To add a worker to this swarm, run the following command:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; docker swarm join --token SWMTKN-1-23t6ldii7xxyyol2ulu0qddlqgwp3i1xpckiij2yjpintebbjq-bw598idhl229sykrhyiykviiw 192.168.1.10:2377
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;尚、既に worker ノードを作成済みであったり、manager ノードを作成しているマシンで &lt;code&gt;docker swarm join&lt;/code&gt; を実行した場合、以下のエラーが表示されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error response from daemon: This node is already part of a swarm. Use &lt;span class="s2"&gt;&amp;#34;docker swarm leave&amp;#34;&lt;/span&gt; to leave this swarm and join another one.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="確認-1"&gt;&lt;a href="#%e7%a2%ba%e8%aa%8d-1" class="header-anchor"&gt;&lt;/a&gt;確認
&lt;/h3&gt;&lt;p&gt;先ほどと同じように &lt;code&gt;docker node ls&lt;/code&gt; で確認できます。&lt;br&gt;
尚、このような Swarm を管理するコマンドは manager ノードが動作しているマシンでのみ実行可能です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker node ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hqi4gtcdh4a7ya8myg0x0my37 worker1 Ready Active 20.10.12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;z9voajpw84i4jk2fomqwsmnc7 * manager1 Ready Active Leader 20.10.7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="サービスのデプロイ"&gt;&lt;a href="#%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%81%ae%e3%83%87%e3%83%97%e3%83%ad%e3%82%a4" class="header-anchor"&gt;&lt;/a&gt;サービスのデプロイ
&lt;/h2&gt;&lt;p&gt;ノードを作成したので、そこにサービスを追加していきます。&lt;br&gt;
まずは manager ノードにサービスを追加します。&lt;br&gt;
上述したように、manager ノードは worker ノードも兼ねることができるので、サービスを動かすこともできます。&lt;/p&gt;
&lt;p&gt;manager ノードが動作しているマシンで &lt;code&gt;docker service create&lt;/code&gt; を実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service create --replicas &lt;span class="m"&gt;1&lt;/span&gt; --name helloworld alpine ping docker.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;84aq1iszx44xq2f3cmohfl2tu
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;verall progress: &lt;span class="m"&gt;1&lt;/span&gt; out of &lt;span class="m"&gt;1&lt;/span&gt; tasks 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1/1: running &lt;span class="o"&gt;[==================================================&lt;/span&gt;&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;verify: Service converged
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここでは、&lt;code&gt;alpine&lt;/code&gt; のベースイメージで &lt;code&gt;helloworld&lt;/code&gt; という名前のコンテナを作成し、コンテナ内で &lt;code&gt;ping docker.com&lt;/code&gt; というコマンドを実行しています。&lt;br&gt;
&lt;code&gt;--replicas 1&lt;/code&gt; はコンテナの数です。&lt;/p&gt;
&lt;h3 id="確認-2"&gt;&lt;a href="#%e7%a2%ba%e8%aa%8d-2" class="header-anchor"&gt;&lt;/a&gt;確認
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;docker service ls&lt;/code&gt; で実行中のサービスを確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME MODE REPLICAS IMAGE PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;84aq1iszx44x helloworld replicated 1/1 alpine:latest 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="サービスの詳細を調べる"&gt;&lt;a href="#%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%81%ae%e8%a9%b3%e7%b4%b0%e3%82%92%e8%aa%bf%e3%81%b9%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;サービスの詳細を調べる
&lt;/h3&gt;&lt;p&gt;別記事に書きました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/04/docker-swarm.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/04/docker-swarm.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サービスのスケール"&gt;&lt;a href="#%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%81%ae%e3%82%b9%e3%82%b1%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;サービスのスケール
&lt;/h2&gt;&lt;p&gt;Swarm で実行しているサービスをスケールするには、&lt;code&gt;docker service scale &amp;lt;サービスID&amp;gt;=&amp;lt;タスク数&amp;gt;&lt;/code&gt; を実行します。&lt;br&gt;
尚、サービス内で実行中のコンテナを「タスク」（task）と呼ぶそうです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service scale &lt;span class="nv"&gt;helloworld&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helloworld scaled to &lt;span class="m"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;overall progress: &lt;span class="m"&gt;5&lt;/span&gt; out of &lt;span class="m"&gt;5&lt;/span&gt; tasks 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1/5: running &lt;span class="o"&gt;[==================================================&lt;/span&gt;&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2/5: running &lt;span class="o"&gt;[==================================================&lt;/span&gt;&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3/5: running &lt;span class="o"&gt;[==================================================&lt;/span&gt;&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4/5: running &lt;span class="o"&gt;[==================================================&lt;/span&gt;&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5/5: running &lt;span class="o"&gt;[==================================================&lt;/span&gt;&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;verify: Service converged 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="確認-3"&gt;&lt;a href="#%e7%a2%ba%e8%aa%8d-3" class="header-anchor"&gt;&lt;/a&gt;確認
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;docker service ps &amp;lt;サービスID&amp;gt;&lt;/code&gt; で確認すると、インスタンスが合計５つになったのが分かります。&lt;br&gt;
タスク（コンテナ）は Swarm のノード間で分散されています。&lt;/p&gt;
&lt;p&gt;また、各ノードで &lt;code&gt;docker ps&lt;/code&gt; を実行することでコンテナの情報が確認できます。&lt;/p&gt;
&lt;h2 id="サービスの削除"&gt;&lt;a href="#%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%81%ae%e5%89%8a%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;サービスの削除
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service rm helloworld
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helloworld
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="確認-4"&gt;&lt;a href="#%e7%a2%ba%e8%aa%8d-4" class="header-anchor"&gt;&lt;/a&gt;確認
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;docker service ls&lt;/code&gt; で helloworld サービスが削除されたのを確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME MODE REPLICAS IMAGE PORTS
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;docker service inspect&lt;/code&gt; で調べようとしてもそんなサービスはないと言われます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service inspect helloworld
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Error: no such service: helloworld, Code: &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;docker ps&lt;/code&gt; でタスク（コンテナ）も削除されたことを確認できます。&lt;/p&gt;
&lt;h2 id="ノードの削除"&gt;&lt;a href="#%e3%83%8e%e3%83%bc%e3%83%89%e3%81%ae%e5%89%8a%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;ノードの削除
&lt;/h2&gt;&lt;p&gt;とりあえずここまでやってみました。&lt;br&gt;
チュートリアルでは次はローリングアップデートとなっていますが、そこはまた今度にします。&lt;/p&gt;
&lt;p&gt;尚、上記サービスは削除しましたが、ノードは残ったままです。&lt;br&gt;
ノードの削除方法（Swarm モードの停止方法）を別記事に書きました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/04/docker-swarm_21.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/04/docker-swarm_21.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://knowledge.sakura.ad.jp/11072/" target="_blank" rel="noopener"
 &gt;https://knowledge.sakura.ad.jp/11072/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://circleci.com/ja/blog/docker-swarm-vs-kubernetes/" target="_blank" rel="noopener"
 &gt;https://circleci.com/ja/blog/docker-swarm-vs-kubernetes/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] Swarm モードの停止</title><link>https://blog.ponkotools.com/posts/2022/04/21/docker-swarm/</link><pubDate>Thu, 21 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/21/docker-swarm/</guid><description>&lt;p&gt;Docker Swarm モードを停止するには、Worker ノードと Manager ノードを削除します。&lt;/p&gt;
&lt;h2 id="worker-ノードの削除"&gt;&lt;a href="#worker-%e3%83%8e%e3%83%bc%e3%83%89%e3%81%ae%e5%89%8a%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;Worker ノードの削除
&lt;/h2&gt;&lt;h3 id="ノードの切り離し"&gt;&lt;a href="#%e3%83%8e%e3%83%bc%e3%83%89%e3%81%ae%e5%88%87%e3%82%8a%e9%9b%a2%e3%81%97" class="header-anchor"&gt;&lt;/a&gt;ノードの切り離し
&lt;/h3&gt;&lt;p&gt;Worker ノードで &lt;code&gt;docker swarm leave&lt;/code&gt; を実行すると、Worker ノードが Swarm から切り離されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker swarm leave
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node left the swarm.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="確認"&gt;&lt;a href="#%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;確認
&lt;/h4&gt;&lt;p&gt;Manager ノードで &lt;code&gt;docker node ls&lt;/code&gt; を実行すると、Worker ノードの &lt;code&gt;STATUS&lt;/code&gt; が &lt;code&gt;Down&lt;/code&gt; になったのが確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker node ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hqi4gtcdh4a7ya8myg0x0my37 worker1 Down Active 20.10.12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;z9voajpw84i4jk2fomqwsmnc7 * manager1 Ready Active Leader 20.10.7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ノードの削除"&gt;&lt;a href="#%e3%83%8e%e3%83%bc%e3%83%89%e3%81%ae%e5%89%8a%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;ノードの削除
&lt;/h3&gt;&lt;p&gt;次に Manager ノードで以下のコマンドを実行すれば、Manager ノードの管理上から Worker ノードが削除されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker node rm &amp;lt;ノードID or ホスト名&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="確認-1"&gt;&lt;a href="#%e7%a2%ba%e8%aa%8d-1" class="header-anchor"&gt;&lt;/a&gt;確認
&lt;/h4&gt;&lt;p&gt;&lt;code&gt;docker node ls&lt;/code&gt; を実行すると、Worker ノードが削除されたのが確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker node ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;z9voajpw84i4jk2fomqwsmnc7 * manager1 Ready Active Leader 20.10.7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="manager-ノードの削除"&gt;&lt;a href="#manager-%e3%83%8e%e3%83%bc%e3%83%89%e3%81%ae%e5%89%8a%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;Manager ノードの削除
&lt;/h2&gt;&lt;p&gt;Manager ノードの削除でも &lt;code&gt;docker swarm leave&lt;/code&gt; を実行しますが、そのまま実行すると以下のようなメッセージが出力されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker swarm leave
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error response from daemon: You are attempting to leave the swarm on a node that is participating as a manager. Removing the last manager erases all current state of the swarm. Use &lt;span class="sb"&gt;`&lt;/span&gt;--force&lt;span class="sb"&gt;`&lt;/span&gt; to ignore this message.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Manager ノードを削除するとSwarm の現在の状態がすべて消去されるために警告が表示されていますが、&lt;code&gt;--force&lt;/code&gt; を指定すれば削除できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker swarm leave --force
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node left the swarm.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一応以下の公式ドキュメントを見ると、もう少し詳しく書いてあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/commandline/swarm_leave/" target="_blank" rel="noopener"
 &gt;https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/commandline/swarm_leave/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;要約すると、Manager ノードが複数いる環境では、Manager ノードを Worker ノードに降格させてから削除するのが安全で、最後の Manager ノードの削除、つまり Manager ノード削除後にその Swarm をもう利用しない場合のみ &lt;code&gt;--force&lt;/code&gt; をつけて削除しろ、という感じでしょうか。&lt;/p&gt;
&lt;h2 id="swarm-が無効になったこを確認"&gt;&lt;a href="#swarm-%e3%81%8c%e7%84%a1%e5%8a%b9%e3%81%ab%e3%81%aa%e3%81%a3%e3%81%9f%e3%81%93%e3%82%92%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;Swarm が無効になったこを確認
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;docker info&lt;/code&gt; を実行すると、出力の中に &lt;code&gt;Swarm: inactive&lt;/code&gt; となっているのが確認できるかと思います。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/Brutus/items/b3dfe5957294caa82669" target="_blank" rel="noopener"
 &gt;https://qiita.com/Brutus/items/b3dfe5957294caa82669&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/engine/reference/commandline/swarm_leave/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/engine/reference/commandline/swarm_leave/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/commandline/swarm_leave/" target="_blank" rel="noopener"
 &gt;https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/commandline/swarm_leave/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.oracle.com/cd/E39368_01/E75728/html/ch06s01s05.html" target="_blank" rel="noopener"
 &gt;https://docs.oracle.com/cd/E39368_01/E75728/html/ch06s01s05.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Portainer を docker-compose で動かす</title><link>https://blog.ponkotools.com/posts/2022/04/19/docker-swarm/</link><pubDate>Tue, 19 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/19/docker-swarm/</guid><description>&lt;p&gt;Docker の GUI 管理ツールである Portainer を docker-compose で動かしてみました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Docker 20.10.7&lt;/li&gt;
&lt;li&gt;portainer-ce 2.11&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="docker-composeyml"&gt;&lt;a href="#docker-composeyml" class="header-anchor"&gt;&lt;/a&gt;docker-compose.yml
&lt;/h2&gt;&lt;p&gt;Docker での動かし方は公式ドキュメントに記載されています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.portainer.io/v/ce-2.11/start/install/server/docker/linux" target="_blank" rel="noopener"
 &gt;https://docs.portainer.io/v/ce-2.11/start/install/server/docker/linux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これを docker-compose に落とし込んだのが以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;3&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;portainer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;portainer/portainer-ce&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;portainer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;unless-stopped&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;portainer_data:/data&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;8000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;9443&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;9443&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;portainer_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;通常 HTTPS で 9443 番ポートで アクセスしますが、HTTP でアクセスしたい場合は 9000 番ポートを使用します。&lt;br&gt;
8000 番ポートは Edge コンピュート機能を使用する場合にのみ必要とありますが、使っていないので詳細はわかりません。
それ以外には特筆すべき点はないかと思います。&lt;/p&gt;
&lt;p&gt;これで http://localhost:9000 にアクセスすれば画面が表示されます。&lt;/p&gt;
&lt;h2 id="portainer-agent-を追加する"&gt;&lt;a href="#portainer-agent-%e3%82%92%e8%bf%bd%e5%8a%a0%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;Portainer Agent を追加する
&lt;/h2&gt;&lt;p&gt;以上で Portainer が使えるようになったのですが、Docker Volume の中が閲覧出来ませんでした。&lt;br&gt;
これを有効化するには、Docker Swarm または Portainer Agent を追加する必要があるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.portainer.io/user/docker/volumes/browse" target="_blank" rel="noopener"
 &gt;https://docs.portainer.io/user/docker/volumes/browse&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Docker Swarm はまた別記事にするとして、ここでは Portainer Agent を追加します。&lt;br&gt;
やり方については以下の記事が参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/64735377/install-portainer-portainer-agent-using-docker-compose" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/64735377/install-portainer-portainer-agent-using-docker-compose&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;3.2&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;portainer/agent&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;/var/lib/docker/volumes:/var/lib/docker/volumes&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;portainer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;portainer/portainer-ce&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="l"&gt;H tcp://agent:9001 --tlsskipverify&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;9000:9000&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;portainer_data:/data&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;portainer_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで Docker Volume の中を閲覧できるようになりました。&lt;/p&gt;
&lt;p&gt;Docker Swarm での動かし方は別記事に書きました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/05/portainer-docker-swarm.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/05/portainer-docker-swarm.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.portainer.io/v/ce-2.11/start/install/server/docker/linux" target="_blank" rel="noopener"
 &gt;https://docs.portainer.io/v/ce-2.11/start/install/server/docker/linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/polarbear08/items/931fe04ec228fad13092" target="_blank" rel="noopener"
 &gt;https://qiita.com/polarbear08/items/931fe04ec228fad13092&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/64735377/install-portainer-portainer-agent-using-docker-compose" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/64735377/install-portainer-portainer-agent-using-docker-compose&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Docker] Swarm モードで動作中のサービスについて調べる</title><link>https://blog.ponkotools.com/posts/2022/04/15/docker-swarm/</link><pubDate>Fri, 15 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/15/docker-swarm/</guid><description>&lt;p&gt;Docker Swarm モードで動作中のサービスについて調べる方法です。&lt;br&gt;
尚、Swarm の管理に関するコマンドは、manager ノード上でのみ実行可能です。&lt;/p&gt;
&lt;h2 id="サービスの一覧を調べる"&gt;&lt;a href="#%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%81%ae%e4%b8%80%e8%a6%a7%e3%82%92%e8%aa%bf%e3%81%b9%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;サービスの一覧を調べる
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;docker service ls&lt;/code&gt; で取得できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME MODE REPLICAS IMAGE PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sgwdtal1gqc7 helloworld replicated 1/1 alpine:latest 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="サービスの詳細を調べる"&gt;&lt;a href="#%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%81%ae%e8%a9%b3%e7%b4%b0%e3%82%92%e8%aa%bf%e3%81%b9%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;サービスの詳細を調べる
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;docker service inspect &amp;lt;サービスID or NAME&amp;gt;&lt;/code&gt; で調べられます。&lt;/p&gt;
&lt;p&gt;しかし、このままだと出力が JSON 形式で見づらいので、&lt;code&gt;--pretty&lt;/code&gt; を付けて見やすくしたほうが良いです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service inspect helloworld --pretty
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID:		sgwdtal1gqc7j0ht0pgl6ehh6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name:		helloworld
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Service Mode:	Replicated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Replicas:	&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Placement:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;UpdateConfig:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Parallelism:	&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; On failure:	pause
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Monitoring Period: 5s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Max failure ratio: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Update order: stop-first
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RollbackConfig:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Parallelism:	&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; On failure:	pause
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Monitoring Period: 5s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Max failure ratio: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Rollback order: stop-first
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ContainerSpec:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Image:		alpine:latest@sha256:4edbd2beb5f78b1014028f4fbb99f3237d9561100b6881aabbf5acce2c4f9454
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Args:		ping 192.168.4.1 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Init:		&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Resources:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Endpoint Mode:	vip
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="サービスがどのノードで動作しているか調べる"&gt;&lt;a href="#%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%81%8c%e3%81%a9%e3%81%ae%e3%83%8e%e3%83%bc%e3%83%89%e3%81%a7%e5%8b%95%e4%bd%9c%e3%81%97%e3%81%a6%e3%81%84%e3%82%8b%e3%81%8b%e8%aa%bf%e3%81%b9%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;サービスがどのノードで動作しているか調べる
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;docker service ps &amp;lt;サービスID or NAME&amp;gt;&lt;/code&gt; で調べられます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service ps helloworld 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aeg3t0tj1emt helloworld.1 alpine:latest manager1 Running Running about a minute ago 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;例えば、１つのサービスが２つのノード上で５タスク動作している場合は以下のような出力になります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker service ps helloworld 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aeg3t0tj1emt helloworld.1 alpine:latest manager1 Running Running &lt;span class="m"&gt;13&lt;/span&gt; minutes ago 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rmf7xhyljero helloworld.2 alpine:latest worker1 Running Running &lt;span class="m"&gt;10&lt;/span&gt; minutes ago 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yfezzc46q7ua helloworld.3 alpine:latest worker1 Running Running &lt;span class="m"&gt;10&lt;/span&gt; minutes ago 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;c3kc1qowfj72 helloworld.4 alpine:latest worker1 Running Running &lt;span class="m"&gt;10&lt;/span&gt; minutes ago 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wudt0zzznt1d helloworld.5 alpine:latest manager1 Running Running &lt;span class="m"&gt;9&lt;/span&gt; minutes ago 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;helloworld&lt;/code&gt; というサービスが５つ動作しており、それが２つのノードに均等に割り振られているのが確認できます。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://docs.docker.jp/engine/swarm/swarm-tutorial/inspect-service.html" target="_blank" rel="noopener"
 &gt;http://docs.docker.jp/engine/swarm/swarm-tutorial/inspect-service.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Ubuntu に GitLab-Runner を直接インストールする</title><link>https://blog.ponkotools.com/posts/2022/04/14/gitlab-runner/</link><pubDate>Thu, 14 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/14/gitlab-runner/</guid><description>&lt;p&gt;docker で GitLab-Runner を動かしたことはありましたが、今回初めてホストに直接インストールしました。&lt;/p&gt;
&lt;p&gt;公式ドキュメントは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.gitlab.com/runner/install/" target="_blank" rel="noopener"
 &gt;https://docs.gitlab.com/runner/install/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="インストール"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;インストール
&lt;/h2&gt;&lt;h3 id="apt-でインストール"&gt;&lt;a href="#apt-%e3%81%a7%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;apt でインストール
&lt;/h3&gt;&lt;p&gt;まずはリポジトリを追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -L &lt;span class="s2"&gt;&amp;#34;https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;apt でインストールします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get install gitlab-runner
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;しかし、この方法でインストールしたら結構古いバージョン (11.2.0) がインストールされてしまいました。&lt;br&gt;
最新のバージョンは 14.9.1 のはずなんですが・・・。&lt;/p&gt;
&lt;p&gt;今動かしている GitLab と互換性がなく上手く動かなったので、最終的には次に示すように deb パッケージからインストールしました。&lt;/p&gt;
&lt;h3 id="deb-パッケージからインストール"&gt;&lt;a href="#deb-%e3%83%91%e3%83%83%e3%82%b1%e3%83%bc%e3%82%b8%e3%81%8b%e3%82%89%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;deb パッケージからインストール
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.gitlab.com/runner/install/linux-manually.html" target="_blank" rel="noopener"
 &gt;https://docs.gitlab.com/runner/install/linux-manually.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ドキュメントだと curl を使うようになっていますが、上手くダウンロードできなかったのと、環境変数 &lt;code&gt;arch&lt;/code&gt; が空だったので、以下のコマンドでダウンロードしました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ wget &lt;span class="s2"&gt;&amp;#34;https://gitlab-runner-downloads.s3.amazonaws.com/latest/deb/gitlab-runner_amd64.deb&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次のコマンドでインストールします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ dpkg -i gitlab-runner_amd64.deb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="gitlab-への登録"&gt;&lt;a href="#gitlab-%e3%81%b8%e3%81%ae%e7%99%bb%e9%8c%b2" class="header-anchor"&gt;&lt;/a&gt;GitLab への登録
&lt;/h2&gt;&lt;p&gt;インストールが完了したら Gitlab-Runner を GitLab に登録します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.gitlab.com/runner/register/index.html#linux" target="_blank" rel="noopener"
 &gt;https://docs.gitlab.com/runner/register/index.html#linux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo gitlab-runner register
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;対話形式で入力していきます。&lt;/p&gt;
&lt;p&gt;まず、GitLab の URL を指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please enter the gitlab-ci coordinator URL &lt;span class="o"&gt;(&lt;/span&gt;e.g. https://gitlab.com/&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;http://gitlab.example
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次にトークンを入力します。&lt;br&gt;
トークンは GitLab に管理者でログインし、Menu &amp;gt; Admin &amp;gt; Runner で確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please enter the gitlab-ci token for this runner:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;U6YYzWyiQYzzfCdDH1dv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ランナーの詳細を入力します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please enter the gitlab-ci description &lt;span class="k"&gt;for&lt;/span&gt; this runner:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ランナーを識別するためのタグを指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please enter the gitlab-ci tags &lt;span class="k"&gt;for&lt;/span&gt; this runner &lt;span class="o"&gt;(&lt;/span&gt;comma separated&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次はオプションなので何も入力せず進みました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter optional maintenance note &lt;span class="k"&gt;for&lt;/span&gt; the runner:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最後にスクリプトの実行方法を指定します。&lt;br&gt;
今回はホスト上で直接実行させたかったので、&lt;code&gt;shell&lt;/code&gt; を指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please enter the executor: virtualbox, docker+machine, docker, docker-ssh, parallels, kubernetes, shell, ssh, docker-ssh+machine:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;GitLab の Menu &amp;gt; Admin &amp;gt; Runner で登録されたことが確認できます。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.gitlab.com/runner/install/" target="_blank" rel="noopener"
 &gt;https://docs.gitlab.com/runner/install/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.gitlab.com/runner/install/linux-manually.html" target="_blank" rel="noopener"
 &gt;https://docs.gitlab.com/runner/install/linux-manually.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.gitlab.com/runner/register/index.html#linux" target="_blank" rel="noopener"
 &gt;https://docs.gitlab.com/runner/register/index.html#linux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>TortoiseGit で過去のコミットの作者（コミッター）を修正する</title><link>https://blog.ponkotools.com/posts/2022/04/13/tortoisegit/</link><pubDate>Wed, 13 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/13/tortoisegit/</guid><description>&lt;p&gt;間違ったアカウント（メールアドレス）でコミットしてしまった場合に、後から TortoiseGit で修正する方法です。&lt;/p&gt;
&lt;p&gt;TortoiseGit で過去のコミットメッセージを変更する方法を以下の記事にまとめていますが、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2017/10/tortoisegit.html" target="_blank" rel="noopener"
 &gt;TortoiseGit でコミットメッセージを変更する&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;コミットメッセージではなく、コミッターの情報を変更したい場合、ここにもう少し手順が必要です。&lt;/p&gt;
&lt;h2 id="まずはコミットメッセージを修正する画面を表示する"&gt;&lt;a href="#%e3%81%be%e3%81%9a%e3%81%af%e3%82%b3%e3%83%9f%e3%83%83%e3%83%88%e3%83%a1%e3%83%83%e3%82%bb%e3%83%bc%e3%82%b8%e3%82%92%e4%bf%ae%e6%ad%a3%e3%81%99%e3%82%8b%e7%94%bb%e9%9d%a2%e3%82%92%e8%a1%a8%e7%a4%ba%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;まずはコミットメッセージを修正する画面を表示する
&lt;/h2&gt;&lt;p&gt;上記のページを参考に、まずはコミットメッセージを修正する画面を表示します。&lt;/p&gt;
&lt;p&gt;そしたら、「コミットを編集/分割する」にチェックを入れて「Amend」をクリックします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="481px" data-flex-grow="200" height="375" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/04/13/tortoisegit/01.webp" width="752"&gt;&lt;/p&gt;
&lt;p&gt;すると、通常コミット時と同じ画面が表示されるので、「作者を設定」にチェックを入れ、右の欄にユーザー名とメールアドレスを入力してコミットします。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="669px" data-flex-grow="278" height="259" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/04/13/tortoisegit/02.webp" width="722"&gt;&lt;/p&gt;
&lt;p&gt;「他のコミットを追加しますか？」という画面が表示されますが、コミッターの修正だけであれば「いいえ」を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="337px" data-flex-grow="140" height="152" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/04/13/tortoisegit/03.webp" width="214"&gt;&lt;/p&gt;
&lt;p&gt;他のコミットも編集する場合は同様に修正していきます。&lt;br&gt;
以上です。&lt;/p&gt;</description></item><item><title>git で clone する場合に 503 エラーが表示される</title><link>https://blog.ponkotools.com/posts/2022/04/12/git/</link><pubDate>Tue, 12 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/12/git/</guid><description>&lt;p&gt;ローカルネットワークにある GitLab からクローンをしようとした際、503 エラーが表示されました。&lt;/p&gt;
&lt;p&gt;ググってみるとプロキシ設定が原因という記事が出てきますが、一応プロキシ設定はしているつもりでした。&lt;/p&gt;
&lt;p&gt;しかし、どうやら Git は ワイルドカードを使ったプロキシ設定を認識してくれないようです。&lt;/p&gt;
&lt;p&gt;今回、環境変数 &lt;code&gt;no_proxy&lt;/code&gt; に &lt;code&gt;192.168.1.*&lt;/code&gt; のように設定していたのですが、これを &lt;code&gt;192.168.1.2&lt;/code&gt; のように指定すると正しく表示されました。&lt;/p&gt;</description></item><item><title>[PySide] ARM アーキテクチャ環境に PySide をインストールできない？</title><link>https://blog.ponkotools.com/posts/2022/04/11/python-pyside/</link><pubDate>Mon, 11 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/11/python-pyside/</guid><description>&lt;p&gt;pip で pyside2 および pyside6 をインストールしようとすると失敗しました。&lt;/p&gt;
&lt;p&gt;デバイスは Jetson Xavier NX です。&lt;br&gt;
表示されたエラーは以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# pip install pyside2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ERROR: Could not find a version that satisfies the requirement pyside2 &lt;span class="o"&gt;(&lt;/span&gt;from versions: none&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ERROR: No matching distribution found &lt;span class="k"&gt;for&lt;/span&gt; pyside2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;調べた感じ、どうやら ARM アーキテクチャの場合、pip では インストールできない？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://forum.qt.io/topic/112813/installing-pyside2-on-raspberry-pi" target="_blank" rel="noopener"
 &gt;https://forum.qt.io/topic/112813/installing-pyside2-on-raspberry-pi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qdmana.com/2022/04/202204030455270855.html" target="_blank" rel="noopener"
 &gt;https://qdmana.com/2022/04/202204030455270855.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PySide2 であれば、一応 apt でビルド済みパッケージをインストールすることはできました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install python3-pyside2*
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;しかし、動かしたいアプリは PySide6 を使っており、PySide6 についてはパッケージが見当たりませんでした。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://forum.qt.io/topic/112813/installing-pyside2-on-raspberry-pi" target="_blank" rel="noopener"
 &gt;https://forum.qt.io/topic/112813/installing-pyside2-on-raspberry-pi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qdmana.com/2022/04/202204030455270855.html" target="_blank" rel="noopener"
 &gt;https://qdmana.com/2022/04/202204030455270855.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Ubuntu に SSD をマウント</title><link>https://blog.ponkotools.com/posts/2022/04/09/ubuntu/</link><pubDate>Sat, 09 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/09/ubuntu/</guid><description>&lt;p&gt;Ubuntu 20.04 のマシンに 2.5インチの SSD を追加し、起動時に自動でマウントするようにしました。&lt;/p&gt;
&lt;p&gt;以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/suisuina/items/7b55a640fdd6b299aa46" target="_blank" rel="noopener"
 &gt;https://qiita.com/suisuina/items/7b55a640fdd6b299aa46&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="手順"&gt;&lt;a href="#%e6%89%8b%e9%a0%86" class="header-anchor"&gt;&lt;/a&gt;手順
&lt;/h2&gt;&lt;h2 id="uuid-の確認"&gt;&lt;a href="#uuid-%e3%81%ae%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;UUID の確認
&lt;/h2&gt;&lt;h3 id="gui-で確認"&gt;&lt;a href="#gui-%e3%81%a7%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;GUI で確認
&lt;/h3&gt;&lt;p&gt;Ubuntu の場合、メニューから &lt;code&gt;disks&lt;/code&gt; を起動すれば、GUI で確認可能です。&lt;/p&gt;
&lt;h3 id="コマンドで確認"&gt;&lt;a href="#%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e3%81%a7%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;コマンドで確認
&lt;/h3&gt;&lt;p&gt;まずは以下のコマンドでウントしたい SSD のパスを探します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo fdisk -l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Device Boot Start End Sectors Size Id Type
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/dev/sda1 &lt;span class="m"&gt;2048&lt;/span&gt; &lt;span class="m"&gt;312580095&lt;/span&gt; &lt;span class="m"&gt;312578048&lt;/span&gt; 149.1G &lt;span class="m"&gt;83&lt;/span&gt; Linux
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今回は &lt;code&gt;/dev/sda1&lt;/code&gt; でした。&lt;br&gt;
次に以下のコマンドで UUID を確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo blkid /dev/sda1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/dev/sda1: &lt;span class="nv"&gt;LABEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ssd&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;74172d4c-526a-42ac-9215-b6ea2dd93d9e&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ext4&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;PARTUUID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cb5573bc-01&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="起動時にマウントするように設定"&gt;&lt;a href="#%e8%b5%b7%e5%8b%95%e6%99%82%e3%81%ab%e3%83%9e%e3%82%a6%e3%83%b3%e3%83%88%e3%81%99%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;起動時にマウントするように設定
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;/etc/fstab&lt;/code&gt; を編集します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo nano /etc/fstab
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;XXXXX /mnt/ssd auto defaults &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今回マウント先は &lt;code&gt;/mnt/ssd&lt;/code&gt; としました。&lt;/p&gt;
&lt;p&gt;再起動して確認します。&lt;/p&gt;</description></item><item><title>Docker イメージの保存先を変更</title><link>https://blog.ponkotools.com/posts/2022/04/08/docker/</link><pubDate>Fri, 08 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/08/docker/</guid><description>&lt;p&gt;ストレージの容量が少ない場合など、新たに SSD を接続し、そちらに Docker イメージを保存する方法です。&lt;/p&gt;
&lt;p&gt;以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/atinfinity/lab/wiki/change_docker_image_directory" target="_blank" rel="noopener"
 &gt;https://github.com/atinfinity/lab/wiki/change_docker_image_directory&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 18.04&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="手順"&gt;&lt;a href="#%e6%89%8b%e9%a0%86" class="header-anchor"&gt;&lt;/a&gt;手順
&lt;/h2&gt;&lt;h3 id="docker-サービスの停止"&gt;&lt;a href="#docker-%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%81%ae%e5%81%9c%e6%ad%a2" class="header-anchor"&gt;&lt;/a&gt;Docker サービスの停止
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo service docker stop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="既存データの退避"&gt;&lt;a href="#%e6%97%a2%e5%ad%98%e3%83%87%e3%83%bc%e3%82%bf%e3%81%ae%e9%80%80%e9%81%bf" class="header-anchor"&gt;&lt;/a&gt;既存データの退避
&lt;/h3&gt;&lt;p&gt;既存のデータは &lt;code&gt;/var/lib/docker&lt;/code&gt; にあるので、これを外部ストレージに移動します。&lt;br&gt;
SSD は &lt;code&gt;/mnt/ssd&lt;/code&gt; にマウントしており、そこに &lt;code&gt;docker&lt;/code&gt; というディレクトリを作成してデータを移動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo mkdir /mnt/ssd/docker
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo rsync -aXS /var/lib/docker/. /mnt/ssd/docker/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="設定変更"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;設定変更
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;/etc/docker/daemon.json&lt;/code&gt; を開きます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo nano /etc/docker/daemon.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下を記述して、保存先を &lt;code&gt;/mnt/ssd/docker&lt;/code&gt; に設定します．&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;graph&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/mnt/ssd/docker&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="設定の反映"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a%e3%81%ae%e5%8f%8d%e6%98%a0" class="header-anchor"&gt;&lt;/a&gt;設定の反映
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl daemon-reload
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo service docker start
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="動作確認"&gt;&lt;a href="#%e5%8b%95%e4%bd%9c%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;動作確認
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker info &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s2"&gt;&amp;#34;Docker Root Dir&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Docker Root Dir: /mnt/ssd/docker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="古いデータを削除"&gt;&lt;a href="#%e5%8f%a4%e3%81%84%e3%83%87%e3%83%bc%e3%82%bf%e3%82%92%e5%89%8a%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;古いデータを削除
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;/var/lib/docker&lt;/code&gt; を削除します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo rm -rf /var/lib/docker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="error-creating-overlay-mount-to-というエラーが表示される"&gt;&lt;a href="#error-creating-overlay-mount-to-%e3%81%a8%e3%81%84%e3%81%86%e3%82%a8%e3%83%a9%e3%83%bc%e3%81%8c%e8%a1%a8%e7%a4%ba%e3%81%95%e3%82%8c%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;&lt;code&gt;error creating overlay mount to&lt;/code&gt; というエラーが表示される
&lt;/h2&gt;&lt;p&gt;Docker コンテナを作成しようとした際に、&lt;code&gt;error creating overlay mount to&lt;/code&gt; みたいなエラーが表示されました。&lt;br&gt;
私の場合はファイルシステムが NTFS だったことが原因でした。&lt;br&gt;
EXT4 でフォーマットすれば正常にできました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/atinfinity/lab/wiki/change_docker_image_directory" target="_blank" rel="noopener"
 &gt;https://github.com/atinfinity/lab/wiki/change_docker_image_directory&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>GitLab の root の初期パスワードを調べる</title><link>https://blog.ponkotools.com/posts/2022/04/07/gitlab/</link><pubDate>Thu, 07 Apr 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/04/07/gitlab/</guid><description>&lt;p&gt;久しぶりに新規に GitLab を構築したら仕様が変わっていて困ったのでメモ。&lt;/p&gt;
&lt;p&gt;以前は初回アクセス時にパスワード変更の画面が表示されていたと思うのですが、GitLab 14.9 では表示されませんでした。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;p&gt;Docker で GitLab を動かしています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;gitlab-ce:14.9.2-ce&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="root-の初期パスワードの確認"&gt;&lt;a href="#root-%e3%81%ae%e5%88%9d%e6%9c%9f%e3%83%91%e3%82%b9%e3%83%af%e3%83%bc%e3%83%89%e3%81%ae%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;root の初期パスワードの確認
&lt;/h2&gt;&lt;p&gt;root でログインするための初期パスワードは &lt;code&gt;/etc/gitlab/initial_root_password&lt;/code&gt; に記載されているそうです。&lt;/p&gt;
&lt;p&gt;今回 Docker で GitLab を動かしているので、以下のようにコンテナに入ってから確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker &lt;span class="nb"&gt;exec&lt;/span&gt; -it gitlab bash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cat /etc/gitlab/initial_root_password&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;gitlab&lt;/code&gt; はコンテナ名です。&lt;/p&gt;
&lt;h2 id="root-の初期パスワードの変更"&gt;&lt;a href="#root-%e3%81%ae%e5%88%9d%e6%9c%9f%e3%83%91%e3%82%b9%e3%83%af%e3%83%bc%e3%83%89%e3%81%ae%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;root の初期パスワードの変更
&lt;/h2&gt;&lt;p&gt;初期パスワードは24時間経ったら削除されるとあるので、ログインできたらパスワードを変更しておきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;右上のユーザーメニューから「Edit Profile」を選択&lt;/li&gt;
&lt;li&gt;サイドメニューより「Password」を選択&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/masa2223/items/78aaf76329637e6ca12d" target="_blank" rel="noopener"
 &gt;https://qiita.com/masa2223/items/78aaf76329637e6ca12d&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>nvidia-docker2 (nvidia-container-toolkit) のインストール</title><link>https://blog.ponkotools.com/posts/2022/03/31/nvidia-docker/</link><pubDate>Thu, 31 Mar 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/03/31/nvidia-docker/</guid><description>&lt;p&gt;Docker コンテナ内で GPU を使うためには NVIDIA Container Toolkit をインストールする必要があります。&lt;/p&gt;
&lt;p&gt;公式ドキュメントは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html" target="_blank" rel="noopener"
 &gt;https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="インストール方法"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;インストール方法
&lt;/h2&gt;&lt;p&gt;上記のページにインストール手順も書いてあります。&lt;br&gt;
（以下は見やすくするためにコマンドを分割しています。）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;distribution&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;. /etc/os-release&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$ID$VERSION_ID&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -s -L https://nvidia.github.io/libnvidia-container/gpgkey &lt;span class="p"&gt;|&lt;/span&gt; sudo apt-key add -
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -s -L https://nvidia.github.io/libnvidia-container/&lt;span class="nv"&gt;$distribution&lt;/span&gt;/libnvidia-container.list &lt;span class="p"&gt;|&lt;/span&gt; sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install -y nvidia-docker2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;nvidia-docker2&lt;/code&gt; がトップレベルのパッケージらしいので、インストールするときは &lt;code&gt;nvidia-container-toolkit&lt;/code&gt; ではなく &lt;code&gt;nvidia-docker2&lt;/code&gt; を指定するようです。&lt;br&gt;
ここらへん以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/tkusumi/items/f275f0737fb5b261a868" target="_blank" rel="noopener"
 &gt;https://qiita.com/tkusumi/items/f275f0737fb5b261a868&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;まぁ公式ドキュメントが &lt;code&gt;nvidia-docker2&lt;/code&gt; をインストールするようになっていますし、それに従えばよいかと。&lt;/p&gt;
&lt;p&gt;また、古い記事では &lt;code&gt;nvidia-docker&lt;/code&gt; と書いてあったりしますが、ここらへんの変遷は以下が参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/ksasaki/items/b20a785e1a0f610efa08" target="_blank" rel="noopener"
 &gt;https://qiita.com/ksasaki/items/b20a785e1a0f610efa08&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="動作確認"&gt;&lt;a href="#%e5%8b%95%e4%bd%9c%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;動作確認
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;nvidia-container-cli&lt;/code&gt; で確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nvidia-container-cli --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cli-version: 1.8.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lib-version: 1.8.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;build date: 2022-02-14T12:02+00:00
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;build revision: abd4e14d8cb923e2a70b7dcfee55fbc16bffa353
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;build compiler: x86_64-linux-gnu-gcc-7 7.5.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;build platform: x86_64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;build flags: -D_GNU_SOURCE -D_FORTIFY_SOURCE&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; -DNDEBUG -std&lt;span class="o"&gt;=&lt;/span&gt;gnu11 -O2 -g -fdata-sections -ffunction-sections -fplan9-extensions -fstack-protector -fno-strict-aliasing -fvisibility&lt;span class="o"&gt;=&lt;/span&gt;hidden -Wall -Wextra -Wcast-align -Wpointer-arith -Wmissing-prototypes -Wnonnull -Wwrite-strings -Wlogical-op -Wformat&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; -Wmissing-format-attribute -Winit-self -Wshadow -Wstrict-prototypes -Wunreachable-code -Wconversion -Wsign-conversion -Wno-unknown-warning-option -Wno-format-extra-args -Wno-gnu-alignof-expression -Wl,-zrelro -Wl,-znow -Wl,-zdefs -Wl,--gc-sections
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nvidia-container-cli info
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NVRM version: 470.103.01
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CUDA version: 11.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Device Index: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Device Minor: &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Model: NVIDIA GeForce RTX &lt;span class="m"&gt;3080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Brand: GeForce
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GPU UUID: GPU-565ac97c-fe71-f49b-1ac0-7ac93c7dab8d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Bus Location: 00000000:01:00.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Architecture: 8.6
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://takake-blog.com/ubuntu-2004-install-nvidiacontainertoolkit/" target="_blank" rel="noopener"
 &gt;https://takake-blog.com/ubuntu-2004-install-nvidiacontainertoolkit/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/tkusumi/items/f275f0737fb5b261a868" target="_blank" rel="noopener"
 &gt;https://qiita.com/tkusumi/items/f275f0737fb5b261a868&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/ksasaki/items/b20a785e1a0f610efa08" target="_blank" rel="noopener"
 &gt;https://qiita.com/ksasaki/items/b20a785e1a0f610efa08&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://gangannikki.hatenadiary.jp/entry/2020/09/26/200000" target="_blank" rel="noopener"
 &gt;https://gangannikki.hatenadiary.jp/entry/2020/09/26/200000&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Ubuntu 20.04 に古い NVIDIA Driver と CUDA をインストール</title><link>https://blog.ponkotools.com/posts/2022/03/30/ubuntu-nvidia/</link><pubDate>Wed, 30 Mar 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/03/30/ubuntu-nvidia/</guid><description>&lt;p&gt;古いグラフィックボードが手に入ったので、それに対応した NVIDIA Driver および CUDA をインストールしたときのメモです。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;GPU：NVIDIA Quadro 2000&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="nvidia-driver-のインストール"&gt;&lt;a href="#nvidia-driver-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;NVIDIA Driver のインストール
&lt;/h2&gt;&lt;p&gt;以下のコマンドでインストールするドライバーのバージョンがわかります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ubuntu-drivers devices
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;または、以下のページで必要なドライバーのバージョンを調べることもできます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.nvidia.com/Download/index.aspx" target="_blank" rel="noopener"
 &gt;https://www.nvidia.com/Download/index.aspx&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上より必要なドライバーは 390 だとわかりました。&lt;br&gt;
ドライバーは上記のページからダウンロードできますが、Ubuntu の場合は apt でインストールしたほうが楽です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt -y install nvidia-driver-390
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一度再起動し、&lt;code&gt;nvidia-smi&lt;/code&gt; でドライバーが正しくインストールされたか確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nvidia-smi
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tue Mar &lt;span class="m"&gt;15&lt;/span&gt; 13:51:47 &lt;span class="m"&gt;2022&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-----------------------------------------------------------------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; NVIDIA-SMI 390.144 Driver Version: 390.144 &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;-------------------------------+----------------------+----------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; GPU Name Persistence-M&lt;span class="p"&gt;|&lt;/span&gt; Bus-Id Disp.A &lt;span class="p"&gt;|&lt;/span&gt; Volatile Uncorr. ECC &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; Fan Temp Perf Pwr:Usage/Cap&lt;span class="p"&gt;|&lt;/span&gt; Memory-Usage &lt;span class="p"&gt;|&lt;/span&gt; GPU-Util Compute M. &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="o"&gt;===============================&lt;/span&gt;+&lt;span class="o"&gt;======================&lt;/span&gt;+&lt;span class="o"&gt;======================&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; Quadro &lt;span class="m"&gt;2000&lt;/span&gt; Off &lt;span class="p"&gt;|&lt;/span&gt; 00000000:01:00.0 On &lt;span class="p"&gt;|&lt;/span&gt; N/A &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; 30% 48C P12 N/A / N/A &lt;span class="p"&gt;|&lt;/span&gt; 577MiB / 964MiB &lt;span class="p"&gt;|&lt;/span&gt; 0% Default &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-------------------------------+----------------------+----------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-----------------------------------------------------------------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; Processes: GPU Memory &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; GPU PID Type Process name Usage &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="o"&gt;=============================================================================&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1193&lt;/span&gt; G /usr/lib/xorg/Xorg 141MiB &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;2102&lt;/span&gt; G /usr/lib/xorg/Xorg 220MiB &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;2276&lt;/span&gt; G /usr/bin/gnome-shell 206MiB &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-----------------------------------------------------------------------------+
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="cuda-のインストール"&gt;&lt;a href="#cuda-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;CUDA のインストール
&lt;/h2&gt;&lt;p&gt;NVIDIA Driver と CUDA のバージョンの関係は以下で確認できます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html" target="_blank" rel="noopener"
 &gt;https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回インストールした NVIDIA Driver は 390.144 なので、CUDA は 9.1 インストールします。&lt;/p&gt;
&lt;p&gt;CUDA のインストール方法ですが、以下でプラットフォームに応じた方法を調べることができます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://developer.nvidia.com/cuda-downloads" target="_blank" rel="noopener"
 &gt;https://developer.nvidia.com/cuda-downloads&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ubuntu 20.04 では以下が表示されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/7fa2af80.pub
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo add-apt-repository &lt;span class="s2"&gt;&amp;#34;deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/ /&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get -y install cuda
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;しかし、このコマンドでは CUDA のバージョンが指定されていないため、実行してしまうと最新の CUDA がインストールされてしまいます。&lt;br&gt;
なので、次に示すように、バージョン 9.1 を指定してインストールしてやります。&lt;/p&gt;
&lt;h2 id="cuda-91-のインストール"&gt;&lt;a href="#cuda-91-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;CUDA 9.1 のインストール
&lt;/h2&gt;&lt;p&gt;CUDA 9.1 をインストールしたいところですが、apt でインストールできる CUDA の一覧を見てみても 9.1 はありません。&lt;br&gt;
なので、以下を参考に Ubuntu 16.04 用のパッケージをインストールしました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/yukoba/items/3692f1cb677b2383c983" target="_blank" rel="noopener"
 &gt;https://qiita.com/yukoba/items/3692f1cb677b2383c983&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/sabaku20XX/items/7f559dd46357cc5adf1e" target="_blank" rel="noopener"
 &gt;https://qiita.com/sabaku20XX/items/7f559dd46357cc5adf1e&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -sL http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub &lt;span class="p"&gt;|&lt;/span&gt; sudo apt-key add
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo dpkg -i cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt --fix-broken install
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install cuda-toolkit-9-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo reboot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ rm cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意点として、apt で &lt;code&gt;cuda-9-1&lt;/code&gt; をインストールすると NVIDIA Driver も最新に更新されてしまうので、&lt;code&gt;cuda-toolkit-9-1&lt;/code&gt; をインストールする必要があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://zenn.dev/takeshita/articles/a02402e59d72a7" target="_blank" rel="noopener"
 &gt;https://zenn.dev/takeshita/articles/a02402e59d72a7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;インストールが完了したら、&lt;code&gt;~/.bashrc&lt;/code&gt; の末尾に以下を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/usr/local/cuda/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/usr/local/cuda/lib64:&lt;/span&gt;&lt;span class="nv"&gt;$LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここで再起動します。&lt;/p&gt;
&lt;h3 id="cuda-バージョンの確認"&gt;&lt;a href="#cuda-%e3%83%90%e3%83%bc%e3%82%b8%e3%83%a7%e3%83%b3%e3%81%ae%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;CUDA バージョンの確認
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;nvidia-smi&lt;/code&gt; で確認できるはずなのですが、私の環境では何も表示されました。&lt;br&gt;
ただ、&lt;code&gt;nvcc&lt;/code&gt; では確認できたので、インストールはされているんじゃないかと。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nvcc -V
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nvcc: NVIDIA &lt;span class="o"&gt;(&lt;/span&gt;R&lt;span class="o"&gt;)&lt;/span&gt; Cuda compiler driver
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; 2005-2017 NVIDIA Corporation
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Built on Fri_Nov__3_21:07:56_CDT_2017
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cuda compilation tools, release 9.1, V9.1.85
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、以下でも確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat /usr/local/cuda/version.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CUDA Version 9.1.85
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="cuda-のインストール後に-nvidia-driver-がおかしくなってしまった場合"&gt;&lt;a href="#cuda-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e5%be%8c%e3%81%ab-nvidia-driver-%e3%81%8c%e3%81%8a%e3%81%8b%e3%81%97%e3%81%8f%e3%81%aa%e3%81%a3%e3%81%a6%e3%81%97%e3%81%be%e3%81%a3%e3%81%9f%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;CUDA のインストール後に NVIDIA Driver がおかしくなってしまった場合
&lt;/h3&gt;&lt;p&gt;前述したように、NVIDIA Driver と CUDA のバージョンが合っていなければ動作がおかしくなります。&lt;/p&gt;
&lt;p&gt;以下を参考に NVIDIA Driver と CUDA を削除してからインストールをやり直す必要があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/not_charge/items/dce7512544a7ead04bca" target="_blank" rel="noopener"
 &gt;https://qiita.com/not_charge/items/dce7512544a7ead04bca&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get --purge remove nvidia-*
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get --purge remove cuda-*
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="docker-コンテナ内で-gpu-が使えるか確認しようとして諦めた"&gt;&lt;a href="#docker-%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e5%86%85%e3%81%a7-gpu-%e3%81%8c%e4%bd%bf%e3%81%88%e3%82%8b%e3%81%8b%e7%a2%ba%e8%aa%8d%e3%81%97%e3%82%88%e3%81%86%e3%81%a8%e3%81%97%e3%81%a6%e8%ab%a6%e3%82%81%e3%81%9f" class="header-anchor"&gt;&lt;/a&gt;docker コンテナ内で GPU が使えるか確認しようとして諦めた
&lt;/h2&gt;&lt;p&gt;せっかく CUDA がインストールできたので、機械学習で GPU が使えそうか確認します。&lt;br&gt;
まず pytorch を使い、ホスト上で以下のコードで確認してみました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;torch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cuda&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_available&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;すると、以下のようにエラーが表示されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;UserWarning: CUDA initialization: The NVIDIA driver on your system is too old &lt;span class="o"&gt;(&lt;/span&gt;found version 9010&lt;span class="o"&gt;)&lt;/span&gt;. Please update your GPU driver by downloading and installing a new version from the URL: http://www.nvidia.com/Download/index.aspx Alternatively, go to: https://pytorch.org to install a PyTorch version that has been compiled with your version of the CUDA driver. &lt;span class="o"&gt;(&lt;/span&gt;Triggered internally at /pytorch/c10/cuda/CUDAFunctions.cpp:115.&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; torch._C._cuda_getDeviceCount&lt;span class="o"&gt;()&lt;/span&gt; &amp;gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;PyTorch のバージョンも CUDA に合わせる必要があるようです。&lt;br&gt;
以下のページを参考に pytorch のバージョンを指定してインストールしてみます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://varhowto.com/install-pytorch-cuda-9-1/" target="_blank" rel="noopener"
 &gt;https://varhowto.com/install-pytorch-cuda-9-1/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;すると以下のエラーが表示されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pip3 install &lt;span class="nv"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;1.1.0 &lt;span class="nv"&gt;torchvision&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;0.3.0 -f https://download.pytorch.org/whl/cu90/torch_stable.html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Looking in links: https://download.pytorch.org/whl/cu90/torch_stable.html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/usr/share/python-wheels/urllib3-1.25.8-py2.py3-none-any.whl/urllib3/connectionpool.py:999: InsecureRequestWarning: Unverified HTTPS request is being made to host &lt;span class="s1"&gt;&amp;#39;172.20.16.253&amp;#39;&lt;/span&gt;. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ERROR: Could not find a version that satisfies the requirement &lt;span class="nv"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;1.1.0 &lt;span class="o"&gt;(&lt;/span&gt;from versions: 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.7.1, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 1.10.0, 1.10.1, 1.10.2, 1.11.0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ERROR: No matching distribution found &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;1.1.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここらへんから面倒になり、先に docker コンテナを作ることにしました。&lt;br&gt;
まずは NVIDIA Container Toolkit をインストールしようと以下のページを見ると、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html" target="_blank" rel="noopener"
 &gt;https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;動作要件が以下のようになっていました。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;GNU/Linux x86_64 with kernel version &amp;gt; 3.10&lt;/li&gt;
&lt;li&gt;Docker &amp;gt;= 19.03 (recommended, but some distributions may include older versions of Docker. The minimum supported version is 1.12)&lt;/li&gt;
&lt;li&gt;NVIDIA GPU with Architecture &amp;gt;= Kepler (or compute capability 3.0)&lt;/li&gt;
&lt;li&gt;NVIDIA Linux drivers &amp;gt;= 418.81.07 (Note that older driver releases or branches are unsupported.)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;というわけでここで諦めました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.nvidia.com/Download/index.aspx" target="_blank" rel="noopener"
 &gt;https://www.nvidia.com/Download/index.aspx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/sabaku20XX/items/7f559dd46357cc5adf1e" target="_blank" rel="noopener"
 &gt;https://qiita.com/sabaku20XX/items/7f559dd46357cc5adf1e&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/porizou1/items/74d8264d6381ee2941bd" target="_blank" rel="noopener"
 &gt;https://qiita.com/porizou1/items/74d8264d6381ee2941bd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/abetomo/items/a114a3c423f110460549" target="_blank" rel="noopener"
 &gt;https://qiita.com/abetomo/items/a114a3c423f110460549&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://shiba6v.hatenablog.com/entry/2018/10/18/021749" target="_blank" rel="noopener"
 &gt;https://shiba6v.hatenablog.com/entry/2018/10/18/021749&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://www-home.htwg-konstanz.de/~MFERTIG/files/tools/NVIDIA_CUDA_Toolkit_9_1_Ubuntu_20_04_2021.txt" target="_blank" rel="noopener"
 &gt;http://www-home.htwg-konstanz.de/~MFERTIG/files/tools/NVIDIA_CUDA_Toolkit_9_1_Ubuntu_20_04_2021.txt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>docker イメージのファイル保存、読み込み</title><link>https://blog.ponkotools.com/posts/2022/03/29/docker/</link><pubDate>Tue, 29 Mar 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/03/29/docker/</guid><description>&lt;p&gt;ネットに繋がらない環境で docker コンテナを動かすために docker イメージをファイルから読み込むことがあったので、そのメモです。&lt;/p&gt;
&lt;h3 id="イメージをファイルに保存"&gt;&lt;a href="#%e3%82%a4%e3%83%a1%e3%83%bc%e3%82%b8%e3%82%92%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ab%e4%bf%9d%e5%ad%98" class="header-anchor"&gt;&lt;/a&gt;イメージをファイルに保存
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker save イメージ名:タグ &amp;gt; filename.tar
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ファイルをロードしてイメージを作成"&gt;&lt;a href="#%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%82%92%e3%83%ad%e3%83%bc%e3%83%89%e3%81%97%e3%81%a6%e3%82%a4%e3%83%a1%e3%83%bc%e3%82%b8%e3%82%92%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;ファイルをロードしてイメージを作成
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker load -i filename.tar
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;または&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker load &amp;lt; filename.tar
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;イメージ名とタグ名はもとのものと同じで読み込まれました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://uxmilk.jp/55512" target="_blank" rel="noopener"
 &gt;https://uxmilk.jp/55512&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] `error in modulated_deformable_im2col_cuda: no kernel image is available for execution on the device` のエラーが表示される</title><link>https://blog.ponkotools.com/posts/2022/03/25/python/</link><pubDate>Fri, 25 Mar 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/03/25/python/</guid><description>&lt;p&gt;pytorch で DCNv2 を使って推論を行っているアプリで、以下のエラーが表示されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;error in modulated_deformable_im2col_cuda: no kernel image is available &lt;span class="k"&gt;for&lt;/span&gt; execution on the device
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Docker コンテナ内でアプリを動かしていたのですが、DCNv2 のビルドをやり直したら解消されました。&lt;br&gt;
具体的には以下の &lt;code&gt;make.sh&lt;/code&gt; を実行します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/jinfagang/DCNv2_latest" target="_blank" rel="noopener"
 &gt;https://github.com/jinfagang/DCNv2_latest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/CharlesShang/DCNv2/issues/113" target="_blank" rel="noopener"
 &gt;https://github.com/CharlesShang/DCNv2/issues/113&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/jinfagang/DCNv2_latest" target="_blank" rel="noopener"
 &gt;https://github.com/jinfagang/DCNv2_latest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Markdown で外部の Markdown ファイルを読み込んで表示</title><link>https://blog.ponkotools.com/posts/2022/03/24/markdown/</link><pubDate>Thu, 24 Mar 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/03/24/markdown/</guid><description>&lt;p&gt;Markdown 自体に外部ファイルを読み込んで表示する構文はないようです。&lt;/p&gt;
&lt;p&gt;しかし、VSCode の Markdown Preview Enhanced というプラグインでは、以下のようにして外部ファイルを読み込んでプレビュー表示することができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;@import &amp;#34;hoge.md&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;詳しい使い方は以下に記載されています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/shd101wyy/markdown-preview-enhanced/blob/master/docs/ja-jp/file-imports.md" target="_blank" rel="noopener"
 &gt;https://github.com/shd101wyy/markdown-preview-enhanced/blob/master/docs/ja-jp/file-imports.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/shd101wyy/markdown-preview-enhanced/blob/master/docs/ja-jp/file-imports.md" target="_blank" rel="noopener"
 &gt;https://github.com/shd101wyy/markdown-preview-enhanced/blob/master/docs/ja-jp/file-imports.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] `most likely due to a circular import` が表示されたときの対処法</title><link>https://blog.ponkotools.com/posts/2022/03/23/python/</link><pubDate>Wed, 23 Mar 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/03/23/python/</guid><description>&lt;p&gt;コードを確認しても正しいはずなのにこのエラーが表示されて困ったことがありました。&lt;/p&gt;
&lt;p&gt;原因は、モジュール名とファイル名が被っていたことでした。&lt;/p&gt;
&lt;p&gt;例えば、ファイル名を &lt;code&gt;pandas.py&lt;/code&gt; とかにして、その中で以下のように pandas を使っていたりするとこのようなエラーが表示されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;pd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;AttributeError: partially initialized module &lt;span class="s1"&gt;&amp;#39;pandas&amp;#39;&lt;/span&gt; has no attribute &lt;span class="s1"&gt;&amp;#39;DataFrame&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;most likely due to a circular import&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;imoprt pandas&lt;/code&gt; で自身のファイルを読み込むことになり、再帰読み込みになってしまっているからです。&lt;br&gt;
知らないと結構はまることになるやつだと思います。&lt;/p&gt;</description></item><item><title>Windows PC から NAS に接続できなくなった</title><link>https://blog.ponkotools.com/posts/2022/03/19/windows-nas/</link><pubDate>Sat, 19 Mar 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/03/19/windows-nas/</guid><description>&lt;p&gt;ちょっと古めの NAS を持っているのですが、Windows 10 の PC からアクセスできなくなりました。&lt;/p&gt;
&lt;p&gt;以前はアクセスできていたはずなのですが、いつの間にかアクセスできなくなっていました。
スマホからはアクセスできているので機器の故障ではなく、またネットワークに問題がないことも確認済みです。&lt;/p&gt;
&lt;p&gt;んで、いろいろ調べていたのですが、どうやらその NAS には SMB1 のプロトコルでアクセスする必要があるみたいで、Windows 10 では機能を有効化しないといけないようです。&lt;/p&gt;
&lt;p&gt;上述したように以前はアクセスできていたはずなんですけど・・・、Windows Update かなんかで設定が変わったんですかね？&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;[スタート]-[Windows システム ツール]-[コントロール パネル] を開く&lt;/li&gt;
&lt;li&gt;[プログラム]-[プログラムと機能] を開く&lt;/li&gt;
&lt;li&gt;[Windows の機能の有効化または無効化] をクリック&lt;/li&gt;
&lt;li&gt;「SMB 1.0/CIFS ファイル共有のサポート」の「SMB 1.0/CIFS クライアント」にチェックを入れて [OK] をクリック&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="separator" style="clear: both;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvBkFniSF_x1RQXALeUAKTtCCXzOmuLyx44Dhabi8ZyiIgVTjqsAVhlsM_pOdUjUO-rdebPkwFXm9AXMC9MMVo14BAFM7Gx0U9tEQpYMTuHqxiCPy3xDHPuvLNyZIqMQWvwf9ALz-yDSR5dnelIov7m7xDRTZVJOytFEislqf6yM9TK7WWSxU5Ue08/s694/smb.png" style="display: block; padding: 1em 0; text-align: center; "&gt;&lt;img alt="" border="0" width="320" data-original-height="615" data-original-width="694" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvBkFniSF_x1RQXALeUAKTtCCXzOmuLyx44Dhabi8ZyiIgVTjqsAVhlsM_pOdUjUO-rdebPkwFXm9AXMC9MMVo14BAFM7Gx0U9tEQpYMTuHqxiCPy3xDHPuvLNyZIqMQWvwf9ALz-yDSR5dnelIov7m7xDRTZVJOytFEislqf6yM9TK7WWSxU5Ue08/s320/smb.png"/&gt;&lt;/a&gt;&lt;/div&gt;
1. [今すぐ再起動]をクリックする。
&lt;p&gt;再起動後にアクセスできるようになりました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.iodata.jp/support/qanda/answer/s30023.htm" target="_blank" rel="noopener"
 &gt;https://www.iodata.jp/support/qanda/answer/s30023.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.iodata.jp/support/qanda/answer/s30381.htm" target="_blank" rel="noopener"
 &gt;https://www.iodata.jp/support/qanda/answer/s30381.htm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] NumPy 入門</title><link>https://blog.ponkotools.com/posts/2022/03/14/numpy/</link><pubDate>Mon, 14 Mar 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/03/14/numpy/</guid><description>&lt;p&gt;Python で高速に数値計算を行うためのライブラリである NumPy の基本的な使い方です。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Python 3.8.10&lt;/li&gt;
&lt;li&gt;numpy 1.22.2&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="インストールとインポート"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%a8%e3%82%a4%e3%83%b3%e3%83%9d%e3%83%bc%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;インストールとインポート
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pip install numpy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;numpy をインポートする際、慣例的に np とすることが多いそうです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="配列の作成"&gt;&lt;a href="#%e9%85%8d%e5%88%97%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;配列の作成
&lt;/h2&gt;&lt;p&gt;NumPy 配列は &lt;code&gt;numpy.array&lt;/code&gt; で作成します。&lt;br&gt;
戻り値の型は &lt;code&gt;numpy.ndarray&lt;/code&gt; となります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 一次元配列&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 二次元配列&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;class &lt;span class="s1"&gt;&amp;#39;numpy.ndarray&amp;#39;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 3&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;class &lt;span class="s1"&gt;&amp;#39;numpy.ndarray&amp;#39;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 3&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; 6&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="空の配列を作成"&gt;&lt;a href="#%e7%a9%ba%e3%81%ae%e9%85%8d%e5%88%97%e3%82%92%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;空の配列を作成
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;class &lt;span class="s1"&gt;&amp;#39;numpy.ndarray&amp;#39;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#(2,3)の形状の配列&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;6.23042070e-307 1.33512376e-306 1.11261230e-306&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;7.56577399e-307 9.34600963e-307 1.15860970e-311&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;class &lt;span class="s1"&gt;&amp;#39;numpy.ndarray&amp;#39;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="配列の自動生成"&gt;&lt;a href="#%e9%85%8d%e5%88%97%e3%81%ae%e8%87%aa%e5%8b%95%e7%94%9f%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;配列の自動生成
&lt;/h2&gt;&lt;h3 id="整数型"&gt;&lt;a href="#%e6%95%b4%e6%95%b0%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;整数型
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;numpy.arange(開始値,終了値,間隔値)&lt;/code&gt; で整数型の配列を作成できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt; &lt;span class="m"&gt;22&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt; &lt;span class="m"&gt;25&lt;/span&gt; &lt;span class="m"&gt;26&lt;/span&gt; &lt;span class="m"&gt;27&lt;/span&gt; &lt;span class="m"&gt;28&lt;/span&gt; &lt;span class="m"&gt;29&lt;/span&gt; 30&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="浮動小数型"&gt;&lt;a href="#%e6%b5%ae%e5%8b%95%e5%b0%8f%e6%95%b0%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;浮動小数型
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;numpy.linspace(開始値,終了値,要素数)&lt;/code&gt; で浮動小数型の配列を作成できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linspace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;21. 22. 23. 24. 25. 26. 27. 28. 29. 30.&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="値が全て0の配列"&gt;&lt;a href="#%e5%80%a4%e3%81%8c%e5%85%a8%e3%81%a60%e3%81%ae%e9%85%8d%e5%88%97" class="header-anchor"&gt;&lt;/a&gt;値が全て0の配列
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;0. 0. 0. 0. 0.&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="値が全て1の配列"&gt;&lt;a href="#%e5%80%a4%e3%81%8c%e5%85%a8%e3%81%a61%e3%81%ae%e9%85%8d%e5%88%97" class="header-anchor"&gt;&lt;/a&gt;値が全て1の配列
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ones&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;1. 1. 1. 1. 1.&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="値が全て同じ任意の値の配列"&gt;&lt;a href="#%e5%80%a4%e3%81%8c%e5%85%a8%e3%81%a6%e5%90%8c%e3%81%98%e4%bb%bb%e6%84%8f%e3%81%ae%e5%80%a4%e3%81%ae%e9%85%8d%e5%88%97" class="header-anchor"&gt;&lt;/a&gt;値が全て同じ任意の値の配列
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;full&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 2&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="値が全て同じ任意の値の5x5の配列"&gt;&lt;a href="#%e5%80%a4%e3%81%8c%e5%85%a8%e3%81%a6%e5%90%8c%e3%81%98%e4%bb%bb%e6%84%8f%e3%81%ae%e5%80%a4%e3%81%ae5x5%e3%81%ae%e9%85%8d%e5%88%97" class="header-anchor"&gt;&lt;/a&gt;値が全て同じ任意の値の5x5の配列
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;full&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 2&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 2&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 2&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 2&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 2&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="単位行列"&gt;&lt;a href="#%e5%8d%98%e4%bd%8d%e8%a1%8c%e5%88%97" class="header-anchor"&gt;&lt;/a&gt;単位行列
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eye&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;1. 0. 0. 0. 0.&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;0. 1. 0. 0. 0.&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;0. 0. 1. 0. 0.&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;0. 0. 0. 1. 0.&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;0. 0. 0. 0. 1.&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="転置"&gt;&lt;a href="#%e8%bb%a2%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;転置
&lt;/h2&gt;&lt;p&gt;以下のいずれかで転置できます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;numpy.transpose(配列)&lt;/li&gt;
&lt;li&gt;配列.transpose()&lt;/li&gt;
&lt;li&gt;配列.T&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上記の３つは同じ挙動です。&lt;br&gt;
また、&lt;code&gt;shape&lt;/code&gt; で行列の形状を確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2x3 の配列を生成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 配列の転置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="m"&gt;96&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt; 98&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;62&lt;/span&gt; &lt;span class="m"&gt;95&lt;/span&gt; 13&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;2, 3&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="m"&gt;96&lt;/span&gt; 62&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;23&lt;/span&gt; 95&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;98&lt;/span&gt; 13&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;3, 2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="転置方法を指定"&gt;&lt;a href="#%e8%bb%a2%e7%bd%ae%e6%96%b9%e6%b3%95%e3%82%92%e6%8c%87%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;転置方法を指定
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2x3x4 の配列を生成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 配列の転置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transpose&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[[&lt;/span&gt;&lt;span class="m"&gt;90&lt;/span&gt; &lt;span class="m"&gt;75&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; 21&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="m"&gt;98&lt;/span&gt; 11&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt; &lt;span class="m"&gt;75&lt;/span&gt; &lt;span class="m"&gt;99&lt;/span&gt; 46&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="m"&gt;72&lt;/span&gt; &lt;span class="m"&gt;48&lt;/span&gt; &lt;span class="m"&gt;52&lt;/span&gt; 2&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;75&lt;/span&gt; &lt;span class="m"&gt;49&lt;/span&gt; 29&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;51&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="m"&gt;41&lt;/span&gt; 40&lt;span class="o"&gt;]]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;2, 3, 4&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[[&lt;/span&gt;&lt;span class="m"&gt;90&lt;/span&gt; &lt;span class="m"&gt;75&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; 21&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;72&lt;/span&gt; &lt;span class="m"&gt;48&lt;/span&gt; &lt;span class="m"&gt;52&lt;/span&gt; 2&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="m"&gt;98&lt;/span&gt; 11&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;75&lt;/span&gt; &lt;span class="m"&gt;49&lt;/span&gt; 29&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt; &lt;span class="m"&gt;75&lt;/span&gt; &lt;span class="m"&gt;99&lt;/span&gt; 46&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;51&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="m"&gt;41&lt;/span&gt; 40&lt;span class="o"&gt;]]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;3, 2, 4&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="平坦化"&gt;&lt;a href="#%e5%b9%b3%e5%9d%a6%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;平坦化
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;flatten&lt;/code&gt; または &lt;code&gt;ravel&lt;/code&gt; で配列を一次元化できます。
&lt;code&gt;flatten&lt;/code&gt; は配列をコピーして平坦化されるそうですが、&lt;code&gt;ravel&lt;/code&gt; は元の配列から変更されるようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2x3x4 の配列を生成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 配列の平坦化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ravel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[[&lt;/span&gt;&lt;span class="m"&gt;17&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="m"&gt;76&lt;/span&gt; 10&lt;span class="o"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;83&lt;/span&gt; &lt;span class="m"&gt;33&lt;/span&gt; &lt;span class="m"&gt;17&lt;/span&gt; 4&lt;span class="o"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;91&lt;/span&gt; &lt;span class="m"&gt;62&lt;/span&gt; 26&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="m"&gt;97&lt;/span&gt; &lt;span class="m"&gt;33&lt;/span&gt; &lt;span class="m"&gt;84&lt;/span&gt; 5&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt; &lt;span class="m"&gt;62&lt;/span&gt; &lt;span class="m"&gt;95&lt;/span&gt; 12&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;41&lt;/span&gt; &lt;span class="m"&gt;93&lt;/span&gt; &lt;span class="m"&gt;28&lt;/span&gt; 46&lt;span class="o"&gt;]]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;2, 3, 4&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;17&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="m"&gt;76&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="m"&gt;83&lt;/span&gt; &lt;span class="m"&gt;33&lt;/span&gt; &lt;span class="m"&gt;17&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;91&lt;/span&gt; &lt;span class="m"&gt;62&lt;/span&gt; &lt;span class="m"&gt;26&lt;/span&gt; &lt;span class="m"&gt;97&lt;/span&gt; &lt;span class="m"&gt;33&lt;/span&gt; &lt;span class="m"&gt;84&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt; &lt;span class="m"&gt;62&lt;/span&gt; &lt;span class="m"&gt;95&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt; &lt;span class="m"&gt;41&lt;/span&gt; &lt;span class="m"&gt;93&lt;/span&gt; &lt;span class="m"&gt;28&lt;/span&gt; 46&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;24,&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="reshape-と-resize"&gt;&lt;a href="#reshape-%e3%81%a8-resize" class="header-anchor"&gt;&lt;/a&gt;reshape と resize
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;reshape&lt;/code&gt; と &lt;code&gt;resize&lt;/code&gt; はどちらも配列の形状を変更するための関数ですが、&lt;code&gt;reshape&lt;/code&gt; は元の配列の要素数が変わるような変更はできないのに対し、&lt;code&gt;resize&lt;/code&gt; は好きな形状に変更することができます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;resize&lt;/code&gt; で元の配列よりもサイズが小さい場合は値が切り捨てられ、大きい場合は複製されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2x3の配列を生成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2x3の配列を3x2の配列に変形する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;reshape 2x3 -&amp;gt; 3x2&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;resize 2x3 -&amp;gt; 3x2&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2x3列の配列を2x2の配列に縮小する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;resize 2x3 -&amp;gt; 2x2&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2x3列の配列を4x5の配列に拡大&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;resize 2x3 -&amp;gt; 4x5&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt; 6&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;24&lt;/span&gt; &lt;span class="m"&gt;44&lt;/span&gt; 17&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;reshape 2x3 -&amp;gt; 3x2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="m"&gt;55&lt;/span&gt; 23&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; 24&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;44&lt;/span&gt; 17&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;resize 2x3 -&amp;gt; 3x2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="m"&gt;55&lt;/span&gt; 23&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; 24&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;44&lt;/span&gt; 17&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;resize 2x3 -&amp;gt; 2x2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="m"&gt;55&lt;/span&gt; 23&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; 24&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;resize 2x3 -&amp;gt; 4x5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt; 44&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;17&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; 24&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;44&lt;/span&gt; &lt;span class="m"&gt;17&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt; 6&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;24&lt;/span&gt; &lt;span class="m"&gt;44&lt;/span&gt; &lt;span class="m"&gt;17&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt; 23&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="四則演算"&gt;&lt;a href="#%e5%9b%9b%e5%89%87%e6%bc%94%e7%ae%97" class="header-anchor"&gt;&lt;/a&gt;四則演算
&lt;/h2&gt;&lt;p&gt;配列同士で四則演算を行う方法として、関数を使用する方法と演算子を使用する方法があります。&lt;br&gt;
ただし、乗算などは一般的な行列の積ではなく、同じ行と列の値同士の積となるようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;arr2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;arr2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arr2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 減算&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;arr2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arr2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 乗算&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;arr2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arr2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 除算&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;arr2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arr2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;140&lt;/span&gt; &lt;span class="m"&gt;250&lt;/span&gt; 360&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;140&lt;/span&gt; &lt;span class="m"&gt;250&lt;/span&gt; 360&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt; &lt;span class="m"&gt;150&lt;/span&gt; 240&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt; &lt;span class="m"&gt;150&lt;/span&gt; 240&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="m"&gt;4000&lt;/span&gt; &lt;span class="m"&gt;10000&lt;/span&gt; 18000&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="m"&gt;4000&lt;/span&gt; &lt;span class="m"&gt;10000&lt;/span&gt; 18000&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;2.5 4. 5. &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;2.5 4. 5. &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://tutorials.chainer.org/ja/08_Introduction_to_NumPy.html" target="_blank" rel="noopener"
 &gt;https://tutorials.chainer.org/ja/08_Introduction_to_NumPy.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/mitsumizo/items/02cb82c06e3d42f5011e" target="_blank" rel="noopener"
 &gt;https://qiita.com/mitsumizo/items/02cb82c06e3d42f5011e&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Ubuntu にリモートデスクトップ接続する</title><link>https://blog.ponkotools.com/posts/2022/03/13/ubuntu/</link><pubDate>Sun, 13 Mar 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/03/13/ubuntu/</guid><description>&lt;p&gt;Windows から Ubuntu にリモートデスクトップで接続する方法です。&lt;/p&gt;
&lt;h2 id="ubuntu-側"&gt;&lt;a href="#ubuntu-%e5%81%b4" class="header-anchor"&gt;&lt;/a&gt;Ubuntu 側
&lt;/h2&gt;&lt;p&gt;Xrdp サーバーをインストールします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt -y install xrdp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="windows-側"&gt;&lt;a href="#windows-%e5%81%b4" class="header-anchor"&gt;&lt;/a&gt;Windows 側
&lt;/h2&gt;&lt;p&gt;リモートデスクトップで Ubuntu の IP アドレスを入力して接続します。&lt;/p&gt;
&lt;h3 id="画面が真っ暗な場合"&gt;&lt;a href="#%e7%94%bb%e9%9d%a2%e3%81%8c%e7%9c%9f%e3%81%a3%e6%9a%97%e3%81%aa%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;画面が真っ暗な場合
&lt;/h3&gt;&lt;p&gt;同じユーザーで既に Ubuntu にログイン済みの場合、真っ暗な画面が表示されます。&lt;/p&gt;
&lt;p&gt;Ubuntu 側で一度ログアウトするか、別途 SSH などで Ubuntu に接続し、以下のコマンドで gnome-session を終了させます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pkill gnome-session
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.server-world.info/query?os=Ubuntu_20.04&amp;amp;p=desktop&amp;amp;f=6" target="_blank" rel="noopener"
 &gt;https://www.server-world.info/query?os=Ubuntu_20.04&amp;p=desktop&amp;f=6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://bracket.hatenablog.com/entry/2020/10/05/031057" target="_blank" rel="noopener"
 &gt;https://bracket.hatenablog.com/entry/2020/10/05/031057&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>暗号資産（仮想通貨）の年末調整・確定申告メモ</title><link>https://blog.ponkotools.com/posts/2022/03/12/currency/</link><pubDate>Sat, 12 Mar 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/03/12/currency/</guid><description>&lt;p&gt;先に言っておきますが、内容の保証はできませんのであしからずご了承ください。&lt;/p&gt;
&lt;p&gt;国内取引所から送付される年間取引報告書を使って確定申告を行います。&lt;br&gt;
海外の取引所については利用していないのでわかりません。&lt;/p&gt;
&lt;h2 id="年末調整"&gt;&lt;a href="#%e5%b9%b4%e6%9c%ab%e8%aa%bf%e6%95%b4" class="header-anchor"&gt;&lt;/a&gt;年末調整
&lt;/h2&gt;&lt;p&gt;基礎控除申告書に給与所得以外の所得の合計額を記入する欄があります。&lt;br&gt;
ここに記入すると副業がばれるんじゃないかと心配になりますが、確定申告する場合はここには何も書かなくていいそうです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://twitter.com/moukon_genius/status/1459088540235563011?s=20" target="_blank" rel="noopener"
 &gt;https://twitter.com/moukon_genius/status/1459088540235563011?s=20&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://twitter.com/madogiwa_salary/status/1328623136992948224?s=20" target="_blank" rel="noopener"
 &gt;https://twitter.com/madogiwa_salary/status/1328623136992948224?s=20&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ちなみに、副業が会社にばれるのは住民税が理由だそうです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.aerial-p.com/media/crypto-salaryman.html" target="_blank" rel="noopener"
 &gt;https://www.aerial-p.com/media/crypto-salaryman.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;確定申告の際に住民税を自分で納付するようにすれば大丈夫だそうです。&lt;/p&gt;
&lt;h2 id="確定申告"&gt;&lt;a href="#%e7%a2%ba%e5%ae%9a%e7%94%b3%e5%91%8a" class="header-anchor"&gt;&lt;/a&gt;確定申告
&lt;/h2&gt;&lt;p&gt;暗号資産の税務上の取り扱いについては、国税庁が以下に公表しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.nta.go.jp/publication/pamph/pdf/virtual_currency_faq_03.pdf" target="_blank" rel="noopener"
 &gt;https://www.nta.go.jp/publication/pamph/pdf/virtual_currency_faq_03.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;暗号資産に関する所得の計算に当たっては、国税庁が公表している暗号資産の計算書を使うと便利だそうです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.nta.go.jp/publication/pamph/shotoku/kakuteishinkokukankei/kasoutuka/index.htm" target="_blank" rel="noopener"
 &gt;https://www.nta.go.jp/publication/pamph/shotoku/kakuteishinkokukankei/kasoutuka/index.htm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上記のページに書いてありますが、暗号資産交換業者から送付される年間取引報告書を利用して計算する場合には、「総平均法用」の計算書を使います。&lt;/p&gt;
&lt;h3 id="申告書の作成"&gt;&lt;a href="#%e7%94%b3%e5%91%8a%e6%9b%b8%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;申告書の作成
&lt;/h3&gt;&lt;p&gt;e-Tax で行います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.e-tax.nta.go.jp/index.html" target="_blank" rel="noopener"
 &gt;https://www.e-tax.nta.go.jp/index.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;「各ソフト・コーナー」＞「確定申告書作成コーナー」を選択します。&lt;/p&gt;
&lt;p&gt;「作成開始」から提出方法を選択し、方法に応じた認証等を行います。&lt;/p&gt;
&lt;p&gt;申告書の作成で、「所得税」を選択します。&lt;/p&gt;
&lt;h3 id="収入金額所得金額の入力"&gt;&lt;a href="#%e5%8f%8e%e5%85%a5%e9%87%91%e9%a1%8d%e6%89%80%e5%be%97%e9%87%91%e9%a1%8d%e3%81%ae%e5%85%a5%e5%8a%9b" class="header-anchor"&gt;&lt;/a&gt;収入金額・所得金額の入力
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;「給与所得」に源泉徴収票を参考に入力&lt;/li&gt;
&lt;li&gt;「雑所得」＞「その他」に計算した暗号資産の所得を入力&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;入力方法については以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.aerial-p.com/media/how-to-fillin-cryptoincome.html" target="_blank" rel="noopener"
 &gt;https://www.aerial-p.com/media/how-to-fillin-cryptoincome.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.cryptact.com/journal/https-www-cryptact-com-journal-02howto-cryptocurrency-taxfiling" target="_blank" rel="noopener"
 &gt;https://www.cryptact.com/journal/https-www-cryptact-com-journal-02howto-cryptocurrency-taxfiling&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="必要経費について"&gt;&lt;a href="#%e5%bf%85%e8%a6%81%e7%b5%8c%e8%b2%bb%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6" class="header-anchor"&gt;&lt;/a&gt;必要経費について
&lt;/h3&gt;&lt;p&gt;以下が参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://coincheck.com/ja/article/411#i3" target="_blank" rel="noopener"
 &gt;https://coincheck.com/ja/article/411#i3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.cryptact.com/journal/https-www-cryptact-com-journal-02howto-cryptocurrency-taxfiling" target="_blank" rel="noopener"
 &gt;https://www.cryptact.com/journal/https-www-cryptact-com-journal-02howto-cryptocurrency-taxfiling&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide] FlowLayout を作成する</title><link>https://blog.ponkotools.com/posts/2022/03/08/pyside/</link><pubDate>Tue, 08 Mar 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/03/08/pyside/</guid><description>&lt;p&gt;Qt でウィンドウの幅によって列数がレスポンシブに変わる（自動で改行される）ようなレイアウトを組むには自分で作成する必要があるみたいです。&lt;/p&gt;
&lt;p&gt;こういうレイアウトを Flow Layout というようです。&lt;/p&gt;
&lt;p&gt;この Flow Layout を、&lt;code&gt;QLayout&lt;/code&gt; を継承して作成する方法が公式ドキュメントに載っています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qt-5/qtwidgets-layouts-flowlayout-example.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qt-5/qtwidgets-layouts-flowlayout-example.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ただ、私の環境ではこのコードをそのまま PySide で実装しても細かい部分の挙動がおかしかったので、以下のページも参考にしつつ修正しました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://discourse.techart.online/t/maya-flowlayout-within-a-scrolllayout/4710" target="_blank" rel="noopener"
 &gt;https://discourse.techart.online/t/maya-flowlayout-within-a-scrolllayout/4710&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://fereria.github.io/reincarnation_tech/11_PySide/02_Tips/11_custom_layout/" target="_blank" rel="noopener"
 &gt;https://fereria.github.io/reincarnation_tech/11_PySide/02_Tips/11_custom_layout/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Python 3.8.10&lt;/li&gt;
&lt;li&gt;PySide 6.2.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;p&gt;以下が作成した &lt;code&gt;FlowLayout&lt;/code&gt; クラスです。&lt;br&gt;
解説などは上記のページに載っているので割愛します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtWidgets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QSizePolicy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QLayout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QLayoutItem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QScrollArea&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtCore&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QRect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QPoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FlowLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QLayout&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hspacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vspacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setContentsMargins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__itemlist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__hSpacing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hspacing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__vSpacing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vspacing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__del__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;takeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;takeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;addItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;QLayoutItem&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__itemlist&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__itemlist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;itemAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__itemlist&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__itemlist&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;takeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__itemlist&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__itemlist&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;expandingDirections&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Orientations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Orientation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hasHeightForWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;heightForWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setGeometry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;QRect&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setGeometry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minimumSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;minimumSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__itemlist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expandedTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minimumSize&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;margins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contentsMargins&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;QSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;margins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;margins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;margins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;margins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;doLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;QRect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;testOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bottom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getContentsMargins&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;effectiveRect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;adjusted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;effectiveRect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;effectiveRect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;lineHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__itemlist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;wid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;spaceX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__hSpacing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;spaceX&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;spaceX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layoutSpacing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QSizePolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PushButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QSizePolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PushButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Horizontal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;spaceY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__vSpacing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;spaceY&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;spaceY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layoutSpacing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QSizePolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PushButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QSizePolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PushButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Vertical&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;nextX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;spaceX&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;nextX&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;spaceX&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;effectiveRect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;lineHeight&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;effectiveRect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;lineHeight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;spaceY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;nextX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;spaceX&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;lineHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;testOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setGeometry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nextX&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;lineHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lineHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;lineHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;effectiveRect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;bottom&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QScrollArea&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;widget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;flowlayout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FlowLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Sample &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;flowlayout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setWidgetResizable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qt-5/qtwidgets-layouts-flowlayout-example.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qt-5/qtwidgets-layouts-flowlayout-example.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://discourse.techart.online/t/maya-flowlayout-within-a-scrolllayout/4710" target="_blank" rel="noopener"
 &gt;https://discourse.techart.online/t/maya-flowlayout-within-a-scrolllayout/4710&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://fereria.github.io/reincarnation_tech/11_PySide/02_Tips/11_custom_layout/" target="_blank" rel="noopener"
 &gt;https://fereria.github.io/reincarnation_tech/11_PySide/02_Tips/11_custom_layout/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] tracemalloc を使ってメモリリークの発生箇所を特定する</title><link>https://blog.ponkotools.com/posts/2022/02/26/python-tracemalloc-/</link><pubDate>Sat, 26 Feb 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/02/26/python-tracemalloc-/</guid><description>&lt;p&gt;メモリの使用量が綺麗に右肩上がりになっているアプリがあったので、メモリリークの発生箇所を特定する方法を調べてみたところ、標準モジュールの &lt;code&gt;tracemalloc&lt;/code&gt; で出来そうなので、使ってみました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;tracemalloc&lt;/code&gt; については以下のページを参考にさせていただきました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kazuhira-r.hatenablog.com/entry/2019/04/19/003328" target="_blank" rel="noopener"
 &gt;https://kazuhira-r.hatenablog.com/entry/2019/04/19/003328&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Python 3.8.10&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;p&gt;スレッド化し、5秒ごとにメモリ使用量トップ10と、メモリ増加量トップ10を表示するようにしてみました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tracemalloc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;threading&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Thread&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MemoryCheker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_running&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__snapshot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__class__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; start&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_running&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__run&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__class__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; stopping&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_running&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__class__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; stopped&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_running&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tracemalloc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;take_snapshot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;top_stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;statistics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;lineno&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;[ Top 10 : &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;stat&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;top_stats&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__snapshot&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;top_stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compare_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__snapshot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;lineno&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;[ Top 10 Difference ]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;stat&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;top_stats&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__snapshot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tracemalloc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;memory_checker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MemoryChecker&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;memory_checker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# do something&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;memory_checker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでメモリリークしている箇所にあたりをつけ、原因を特定することができました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kazuhira-r.hatenablog.com/entry/2019/04/19/003328" target="_blank" rel="noopener"
 &gt;https://kazuhira-r.hatenablog.com/entry/2019/04/19/003328&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide] QListWidget の使い方</title><link>https://blog.ponkotools.com/posts/2022/02/25/pyside/</link><pubDate>Fri, 25 Feb 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/02/25/pyside/</guid><description>&lt;p&gt;QListWidget を使っていていろいろはまったのでメモです。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Python 3.8.10&lt;/li&gt;
&lt;li&gt;PySide 6.2.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="カスタムウィジェットをセットする"&gt;&lt;a href="#%e3%82%ab%e3%82%b9%e3%82%bf%e3%83%a0%e3%82%a6%e3%82%a3%e3%82%b8%e3%82%a7%e3%83%83%e3%83%88%e3%82%92%e3%82%bb%e3%83%83%e3%83%88%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;カスタムウィジェットをセットする
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;setItemWidget&lt;/code&gt; でアイテムとウィジェットを関連付けする必要があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;custom_widget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CustomWidget&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Create QListWidgetItem&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QListWidgetItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list_widget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Set size hint&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setSizeHint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;custom_widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Add QListWidgetItem into QListWidget&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setItemWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;custom_widget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="先頭行に追加する"&gt;&lt;a href="#%e5%85%88%e9%a0%ad%e8%a1%8c%e3%81%ab%e8%bf%bd%e5%8a%a0%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;先頭行に追加する
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;insertItem()&lt;/code&gt; で 0 行目にアイテムを追加すればいいと思っていたら、実際には最後に追加されてしまいました。&lt;br&gt;
悩んでいたところで以下の記事を見つけたのですが、どうやら &lt;code&gt;QListWidgetItem&lt;/code&gt; でアイテムを作成する際、親ウィジェットを指定してはいけないようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/45258159/how-to-add-a-qlistwidgetitem-on-top-of-the-qlistwidget" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/45258159/how-to-add-a-qlistwidgetitem-on-top-of-the-qlistwidget&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;custom_widget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CustomWidget&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Create QListWidgetItem&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QListWidgetItem&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# 親を指定しない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Set size hint&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setSizeHint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;custom_widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Add QListWidgetItem into QListWidget&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insertItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setItemWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;custom_widget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ちなみに、&lt;code&gt;insertItem&lt;/code&gt; よりも &lt;code&gt;setItemWidget&lt;/code&gt; を先に処理していると上手く動きませんでした。&lt;/p&gt;
&lt;h2 id="アイテムを削除する"&gt;&lt;a href="#%e3%82%a2%e3%82%a4%e3%83%86%e3%83%a0%e3%82%92%e5%89%8a%e9%99%a4%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;アイテムを削除する
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;takeItem&lt;/code&gt; を使います。&lt;br&gt;
削除なのに take というのが分かりづらい・・・。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;takeItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;removeItemWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://doc.qt.io/qt-5/qlistwidget.html#takeItem" target="_blank" rel="noopener"
 &gt;ドキュメント&lt;/a&gt;によれば、リストから削除されても実体は残っているようなので、&lt;code&gt;del&lt;/code&gt; で削除しています。&lt;br&gt;
だから take なのかな？&lt;/p&gt;
&lt;p&gt;ちなみに &lt;code&gt;removeItemWidget&lt;/code&gt; はアイテムと関連付けられているウィジェットを削除しますが、&lt;code&gt;del item&lt;/code&gt; としているので、もしかしたら不要かもしれません。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/tatsuteb/items/959700c1d7b42c7c8b5a" target="_blank" rel="noopener"
 &gt;https://qiita.com/tatsuteb/items/959700c1d7b42c7c8b5a&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="qlistwidget-のサイズをコンテンツに合わせる"&gt;&lt;a href="#qlistwidget-%e3%81%ae%e3%82%b5%e3%82%a4%e3%82%ba%e3%82%92%e3%82%b3%e3%83%b3%e3%83%86%e3%83%b3%e3%83%84%e3%81%ab%e5%90%88%e3%82%8f%e3%81%9b%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;QListWidget のサイズをコンテンツに合わせる
&lt;/h2&gt;&lt;p&gt;カスタムウィジェットのサイズに上手く合わないことがあったので、どうしたらいいのか調べていたら、以下の記事を見つけました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/6337589/qlistwidget-adjust-size-to-content" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/6337589/qlistwidget-adjust-size-to-content&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下のように &lt;code&gt;sizeHint()&lt;/code&gt; をオーバーライドすればいいようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sizeHintForColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ただ、私の場合、上記だとウィジェットとスクロールバーが重なって表示されたりしたので、以下のようにスクロールバーの幅も考慮するように変更しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sizeHintForColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verticalScrollBar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/948444/qlistview-qlistwidget-with-custom-items-and-custom-item-widgets" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/948444/qlistview-qlistwidget-with-custom-items-and-custom-item-widgets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/45258159/how-to-add-a-qlistwidgetitem-on-top-of-the-qlistwidget" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/45258159/how-to-add-a-qlistwidgetitem-on-top-of-the-qlistwidget&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/tatsuteb/items/959700c1d7b42c7c8b5a" target="_blank" rel="noopener"
 &gt;https://qiita.com/tatsuteb/items/959700c1d7b42c7c8b5a&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/6337589/qlistwidget-adjust-size-to-content" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/6337589/qlistwidget-adjust-size-to-content&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/59428906/qlistwidget-display-more-items" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/59428906/qlistwidget-display-more-items&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Blogger のテーマが保存できない</title><link>https://blog.ponkotools.com/posts/2022/02/24/blogger/</link><pubDate>Thu, 24 Feb 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/02/24/blogger/</guid><description>&lt;p&gt;Blogger テーマの「HTML を編集」で保存した際、以下のように「更新できません」と表示されどうしようもなくなったことがありました。&lt;/p&gt;
&lt;p&gt;何回試しても、「処理しています&amp;hellip;」が長く表示された後、「更新できませんでした」と表示されます。&lt;/p&gt;
&lt;p&gt;原因ですが、いろいろ試行錯誤してみた結果、どうやらテンプレートの文字数が多すぎたようです。&lt;/p&gt;
&lt;p&gt;外部の JavaScript ファイルや CSS ファイルのコードを直接埋め込んでいるところがあったのですが、それを CDN から読み込むように変更したところ、正しく更新できるようになりました。&lt;/p&gt;</description></item><item><title>[PySide] QThread を使って時間のかかる処理をスレッド化する</title><link>https://blog.ponkotools.com/posts/2022/02/20/pyside/</link><pubDate>Sun, 20 Feb 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/02/20/pyside/</guid><description>&lt;p&gt;例えばボタンをクリックしたときに重い処理を実行する場合など、そのまま処理すると GUI が固まってしまうため、スレッド化してやります。&lt;/p&gt;
&lt;h2 id="概要"&gt;&lt;a href="#%e6%a6%82%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;概要
&lt;/h2&gt;&lt;p&gt;python の標準モジュールに &lt;code&gt;threading&lt;/code&gt; がありますが、PySide を使っている場合は &lt;code&gt;QThread&lt;/code&gt; を使います。&lt;br&gt;
本質的にはどちらも同じだそうですが、Signal/Slot など、Qt との対話を行うなら &lt;code&gt;QThread&lt;/code&gt; を使ったほうが良いようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/1595649/threading-in-a-pyqt-application-use-qt-threads-or-python-threads" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/1595649/threading-in-a-pyqt-application-use-qt-threads-or-python-threads&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ちなみに、Qt には &lt;code&gt;QtConcurrent&lt;/code&gt; という &lt;code&gt;QThread&lt;/code&gt; よりも高レベルな API がありますが、こちらは PySide では提供されていないようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/32378719/qtconcurrent-in-pyside-pyqt" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/32378719/qtconcurrent-in-pyside-pyqt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qtforpython/overviews/qtconcurrentrun.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qtforpython/overviews/qtconcurrentrun.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;QThread&lt;/code&gt; のドキュメントは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qtforpython/PySide6/QtCore/QThread.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qtforpython/PySide6/QtCore/QThread.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、PySide で GUI を止めることなく重い処理をするサンプルとして、以下がありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qtforpython/examples/example_corelib__threads.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qtforpython/examples/example_corelib__threads.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上記のサンプルでは &lt;code&gt;QThread&lt;/code&gt; を継承し、&lt;code&gt;run&lt;/code&gt; をオーバーライドしていますが、このやり方は良くないそうで、&lt;code&gt;moveToThread&lt;/code&gt; を使って処理をスレッドに渡すやり方のほうが一般的なようです。&lt;br&gt;
詳しくは以下で解説されています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/hermit4/items/1606750332d1d2685bdb" target="_blank" rel="noopener"
 &gt;https://qiita.com/hermit4/items/1606750332d1d2685bdb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.fixes.pub/program/426883.html" target="_blank" rel="noopener"
 &gt;https://www.fixes.pub/program/426883.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;とはいえ、&lt;code&gt;moveToThread&lt;/code&gt; を使った公式のサンプルが見当たらなかったので、知らない人は知らないんじゃないかなぁと思ったり・・。&lt;/p&gt;
&lt;p&gt;というわけで、&lt;code&gt;QThread&lt;/code&gt; と &lt;code&gt;moveToThread&lt;/code&gt; 使ったスレッド化のサンプルです。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Python 3.8.10&lt;/li&gt;
&lt;li&gt;PySide 6.2.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;p&gt;解説は後にして、まずはコード全体です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;threading&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtWidgets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtCore&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QThread&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Slot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;shiboken6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QObject&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;バックグラウンドで処理を行うクラス
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;countup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_canceled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;worker started, thread_id=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_ident&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_canceled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;countup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;worker finished, thread_id=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_ident&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_canceled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;メインウィンドウ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Start&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clicked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Stop&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clicked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__stop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QLabel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;開始
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;start, thread_id=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_ident&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QThread&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__worker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;moveToThread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 別スレッドで処理を実行する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# シグナルスロットの接続（self.__countup をスレッド側で実行させるために Qt.DirectConnection を指定）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__worker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;countup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__countup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DirectConnection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# スレッドが開始されたら worker の処理を開始する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;started&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__worker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ラムダ式を使う場合は Qt.DirectConnection を指定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#self.__thread.started.connect(lambda: self.__worker.run(), type=Qt.DirectConnection) &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# スレッドが終了したら破棄する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;finished&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__worker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deleteLater&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;finished&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deleteLater&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 処理開始&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;停止
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;stop, thread_id=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_ident&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;shiboken6&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# スレッドが作成されていて、削除されていない&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isRunning&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isFinished&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;thread is stopping&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__worker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;thread is stopped&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__countup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;countup シグナルに対する処理
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__label&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;count=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, thread_id=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_ident&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;closeEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;closeEvent のオーバーライド（ウィンドウを閉じたときにスレッドを終了させる）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;main_window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;main_window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;カウントアップした変数の内容を表示するだけのシンプルなコードです。&lt;br&gt;
スロットがどのスレッドで実行されているかわかるように、スレッドIDも表示しています。&lt;/p&gt;
&lt;div class="separator" style="clear: both;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/a/AVvXsEhB-Rto-nlujv3hZAq2N-GgfoyaNR0AFZfAJcvqSB_Egi_oOVPq3tq89NYFxRVm4yJ_LR_qhmr0QkyhUYxWB4VRJbSADL7rkBLeNTQ3M5RsFNJDGMYWqZotYqvEj_PmYkVnGb9UKn2FR939SejtYr2gwkp6GhSZnTtiQmQzqd7p5OdT1oOME_Afza9l=s317" style="display: block; padding: 1em 0; text-align: center; "&gt;&lt;img alt="" border="0" width="320" data-original-height="193" data-original-width="317" src="https://blogger.googleusercontent.com/img/a/AVvXsEhB-Rto-nlujv3hZAq2N-GgfoyaNR0AFZfAJcvqSB_Egi_oOVPq3tq89NYFxRVm4yJ_LR_qhmr0QkyhUYxWB4VRJbSADL7rkBLeNTQ3M5RsFNJDGMYWqZotYqvEj_PmYkVnGb9UKn2FR939SejtYr2gwkp6GhSZnTtiQmQzqd7p5OdT1oOME_Afza9l=s320"/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h2 id="簡単な解説"&gt;&lt;a href="#%e7%b0%a1%e5%8d%98%e3%81%aa%e8%a7%a3%e8%aa%ac" class="header-anchor"&gt;&lt;/a&gt;簡単な解説
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Worker&lt;/code&gt; が別スレッドで行いたい処理ですが、こいつ自身はスレッド云々を意識せず（どこで実行されるかを意識せず）、処理内容のみを責務としています。&lt;br&gt;
どこで実行するかを意識するのは、処理を開始する &lt;code&gt;MainWindow&lt;/code&gt; です。&lt;/p&gt;
&lt;h3 id="シグナルスロット接続時の注意"&gt;&lt;a href="#%e3%82%b7%e3%82%b0%e3%83%8a%e3%83%ab%e3%82%b9%e3%83%ad%e3%83%83%e3%83%88%e6%8e%a5%e7%b6%9a%e6%99%82%e3%81%ae%e6%b3%a8%e6%84%8f" class="header-anchor"&gt;&lt;/a&gt;シグナルスロット接続時の注意
&lt;/h3&gt;&lt;p&gt;以下の部分です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__worker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;countup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__countup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DirectConnection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;self.__countup&lt;/code&gt; は &lt;code&gt;MainWindow&lt;/code&gt; 内の関数なので、普通に接続するとメインスレッド側で処理が行われてしまいます。&lt;br&gt;
これをスレッド側で処理が行われるようにするには &lt;code&gt;Qt.DirectConnection&lt;/code&gt; を指定する必要があります。&lt;br&gt;
&lt;code&gt;countup&lt;/code&gt; シグナルはスレッド側で動いている &lt;code&gt;Worker&lt;/code&gt; で emit されるので、&lt;code&gt;Qt.DirectConnection&lt;/code&gt; を指定することでシグナルを emit するスレッド側での実行を指定することになります。&lt;br&gt;
ここらへん、以下で詳しく解説されています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/hermit4/items/1606750332d1d2685bdb#connect%E3%81%AE%E7%A8%AE%E9%A1%9E" target="_blank" rel="noopener"
 &gt;https://qiita.com/hermit4/items/1606750332d1d2685bdb#connect%E3%81%AE%E7%A8%AE%E9%A1%9E&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://teratail.com/questions/168096" target="_blank" rel="noopener"
 &gt;https://teratail.com/questions/168096&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ちなみに、以下のスレッド開始時の処理ですが、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;started&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__worker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;self.__worker&lt;/code&gt; は &lt;code&gt;moveToThread&lt;/code&gt; でスレッド側で処理を行うように指定しているので、 明示的に &lt;code&gt;Qt.DirectConnection&lt;/code&gt; を指定しなくてもよいのですが、これを仮に以下のようにラムダ式などを使った場合は、上記と同じ理由で &lt;code&gt;Qt.DirectConnection&lt;/code&gt; を指定する必要があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;started&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__worker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DirectConnection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;例えば、&lt;code&gt;self.__worker.run&lt;/code&gt; に引数を与えて開始したい場合などはこういうケースもあるのではないかと思います。&lt;br&gt;
でもその場合 &lt;code&gt;moveToThread&lt;/code&gt; を使う意味がなくなりそうですが・・・。（実際、&lt;code&gt;moveToThread&lt;/code&gt; を使わなくても上手く動きます。）&lt;/p&gt;
&lt;h3 id="終了処理"&gt;&lt;a href="#%e7%b5%82%e4%ba%86%e5%87%a6%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;終了処理
&lt;/h3&gt;&lt;p&gt;スレッドが終了したら &lt;code&gt;deleteLater&lt;/code&gt; でオブジェクトの破棄を行っています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;finished&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__worker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deleteLater&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;finished&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deleteLater&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://tukunen13.hatenablog.jp/entry/2017/05/25/004652" target="_blank" rel="noopener"
 &gt;https://tukunen13.hatenablog.jp/entry/2017/05/25/004652&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、スレッドを開始したままウィンドウを閉じたときのために、&lt;code&gt;closeEvent&lt;/code&gt; をオーバーライドしてスレッドを停止するようにしています。&lt;/p&gt;
&lt;h3 id="オブジェクトの判定"&gt;&lt;a href="#%e3%82%aa%e3%83%96%e3%82%b8%e3%82%a7%e3%82%af%e3%83%88%e3%81%ae%e5%88%a4%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;オブジェクトの判定
&lt;/h3&gt;&lt;p&gt;Start ボタンを押したときにスレッドを停止してから再度開始していますが、その際に既にスレッドが破棄されていないかどうか判定しています。&lt;br&gt;
オブジェクトが破棄されているかどうかは &lt;code&gt;shiboken&lt;/code&gt; を使います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/11328219/how-to-know-if-object-gets-deleted-in-python" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/11328219/how-to-know-if-object-gets-deleted-in-python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="スレッドの終了判定"&gt;&lt;a href="#%e3%82%b9%e3%83%ac%e3%83%83%e3%83%89%e3%81%ae%e7%b5%82%e4%ba%86%e5%88%a4%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;スレッドの終了判定
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;QThread&lt;/code&gt; に &lt;code&gt;isRunning&lt;/code&gt; と &lt;code&gt;isFinished&lt;/code&gt; という関数がありますが、どっちを使えばいいのかいまいち分からなかったので両方見るようにしました。&lt;br&gt;
ここらへん微妙です・・・。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/1595649/threading-in-a-pyqt-application-use-qt-threads-or-python-threads" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/1595649/threading-in-a-pyqt-application-use-qt-threads-or-python-threads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qtforpython/PySide6/QtCore/QThread.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qtforpython/PySide6/QtCore/QThread.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://fereria.github.io/reincarnation_tech/11_PySide/02_Tips/06_qthread_01/" target="_blank" rel="noopener"
 &gt;https://fereria.github.io/reincarnation_tech/11_PySide/02_Tips/06_qthread_01/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://srinikom.github.io/pyside-docs/PySide/QtCore/QThread.html" target="_blank" rel="noopener"
 &gt;https://srinikom.github.io/pyside-docs/PySide/QtCore/QThread.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://theolizer.com/cpp-school4/cpp-school4-8/" target="_blank" rel="noopener"
 &gt;https://theolizer.com/cpp-school4/cpp-school4-8/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://code.tiblab.net/python/pyside/thread_ui_change" target="_blank" rel="noopener"
 &gt;https://code.tiblab.net/python/pyside/thread_ui_change&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://realpython.com/python-pyqt-qthread/" target="_blank" rel="noopener"
 &gt;https://realpython.com/python-pyqt-qthread/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://tukunen13.hatenablog.jp/entry/2017/05/25/004652" target="_blank" rel="noopener"
 &gt;https://tukunen13.hatenablog.jp/entry/2017/05/25/004652&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/11328219/how-to-know-if-object-gets-deleted-in-python" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/11328219/how-to-know-if-object-gets-deleted-in-python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide] QPushButton にレイアウトを設定している場合にサイズがおかしい</title><link>https://blog.ponkotools.com/posts/2022/02/19/pyside/</link><pubDate>Sat, 19 Feb 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/02/19/pyside/</guid><description>&lt;p&gt;&lt;code&gt;QPushButton&lt;/code&gt; に &lt;code&gt;QVBoxLayout&lt;/code&gt; などを &lt;code&gt;setLayout()&lt;/code&gt; で設定している場合に、ボタンの縦のサイズが小さすぎてレイアウトが潰れた状態になりました。&lt;/p&gt;
&lt;p&gt;レイアウトのサイズに応じてボタンのサイズを変更するにはどうしたらいいのかと悩んでいたら以下の記事を見つけました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/61571582/qt-qpushbutton-vertical-size-fit-to-contents" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/61571582/qt-qpushbutton-vertical-size-fit-to-contents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;sizeHint()&lt;/code&gt; をオーバーライドし、レイアウトが設定されていればそのサイズを、設定されていなければ基底クラスのサイズを返せばいいようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PySide 6.2.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# the button now has a layout, return its size hint&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# no layout set, return the result of the default implementation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sizeHint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/61571582/qt-qpushbutton-vertical-size-fit-to-contents" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/61571582/qt-qpushbutton-vertical-size-fit-to-contents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] マルチスレッド</title><link>https://blog.ponkotools.com/posts/2022/02/18/python/</link><pubDate>Fri, 18 Feb 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/02/18/python/</guid><description>&lt;p&gt;python でのスレッドの作成、開始、終了の方法です。いつもどうだったっけ？となるので、出来るだけシンプルなコードでメモしておきます。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Python 3.8.10&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="スレッドの起動と停止"&gt;&lt;a href="#%e3%82%b9%e3%83%ac%e3%83%83%e3%83%89%e3%81%ae%e8%b5%b7%e5%8b%95%e3%81%a8%e5%81%9c%e6%ad%a2" class="header-anchor"&gt;&lt;/a&gt;スレッドの起動と停止
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;threading&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Thread&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_running&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;start&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_running&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__run&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;stopping&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_running&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;stopped&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_running&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; running&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="排他処理"&gt;&lt;a href="#%e6%8e%92%e4%bb%96%e5%87%a6%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;排他処理
&lt;/h3&gt;&lt;p&gt;上記をベースに、スレッドを複数開始しないように排他をかけてみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;threading&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Lock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_running&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_running&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;already running&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;start&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_running&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__run&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_running&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;not running&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;stopping&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_running&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;stopped&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__is_running&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; running&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;with&lt;/code&gt; の代わりに &lt;code&gt;acquire&lt;/code&gt; と &lt;code&gt;release&lt;/code&gt; を使ってもいいです。&lt;/p&gt;
&lt;p&gt;** 出力結果 **&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;start
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;already running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;already running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-02-14 14:29:16.802901 running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;stopping
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;stopped
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;not running
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;not running
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="既にスレッド起動中の場合は一度停止してから再起動"&gt;&lt;a href="#%e6%97%a2%e3%81%ab%e3%82%b9%e3%83%ac%e3%83%83%e3%83%89%e8%b5%b7%e5%8b%95%e4%b8%ad%e3%81%ae%e5%a0%b4%e5%90%88%e3%81%af%e4%b8%80%e5%ba%a6%e5%81%9c%e6%ad%a2%e3%81%97%e3%81%a6%e3%81%8b%e3%82%89%e5%86%8d%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;既にスレッド起動中の場合は一度停止してから再起動
&lt;/h3&gt;&lt;p&gt;上記の &lt;code&gt;print('already running')&lt;/code&gt; のところで &lt;code&gt;self.stop()&lt;/code&gt; をコールすればよいです。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/tag1216/items/2dcb112f8018eb19a999" target="_blank" rel="noopener"
 &gt;https://qiita.com/tag1216/items/2dcb112f8018eb19a999&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/GRGSIBERIA/items/5e5d6d7afb40a7fc5c34" target="_blank" rel="noopener"
 &gt;https://qiita.com/GRGSIBERIA/items/5e5d6d7afb40a7fc5c34&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://udemyfun.com/python-threading-lock/" target="_blank" rel="noopener"
 &gt;https://udemyfun.com/python-threading-lock/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide] インスタンスが破棄されているかどうかを調べる</title><link>https://blog.ponkotools.com/posts/2022/02/17/pyside/</link><pubDate>Thu, 17 Feb 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/02/17/pyside/</guid><description>&lt;p&gt;PySide を使っていて、既にインスタンスが破棄されているオブジェクトにアクセスした際、以下のようなエラーが表示されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RuntimeError: Internal C++ object (PySide6.QtCore.QThread) already deleted.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これを回避するため、インスタンスが破棄されているかどうかを知るにはどうすればいいか調べてみたところ、以下が見つかりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow-com.translate.goog/questions/11328219/how-to-know-if-object-gets-deleted-in-python?_x_tr_sl=en&amp;amp;_x_tr_tl=ja&amp;amp;_x_tr_hl=ja&amp;amp;_x_tr_pto=wapp" target="_blank" rel="noopener"
 &gt;https://stackoverflow-com.translate.goog/questions/11328219/how-to-know-if-object-gets-deleted-in-python?_x_tr_sl=en&amp;_x_tr_tl=ja&amp;_x_tr_hl=ja&amp;_x_tr_pto=wapp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;shiboken&lt;/code&gt; というモジュールを使えばいいそうです。&lt;br&gt;
公式ドキュメントは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qtforpython/shiboken6/shibokenmodule.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qtforpython/shiboken6/shibokenmodule.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;PySide 6.2.2.1&lt;/li&gt;
&lt;li&gt;Python 3.8.10&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;shiboken6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="n"&gt;shiboken6&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/11328219/how-to-know-if-object-gets-deleted-in-python" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/11328219/how-to-know-if-object-gets-deleted-in-python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qtforpython/shiboken6/shibokenmodule.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qtforpython/shiboken6/shibokenmodule.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] datetime の strftime で Invalid format string になる</title><link>https://blog.ponkotools.com/posts/2022/02/16/python/</link><pubDate>Wed, 16 Feb 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/02/16/python/</guid><description>&lt;p&gt;&lt;code&gt;strftime&lt;/code&gt; で datetime から文字列に変換する際、Ubuntu では上手く動くのに、Windows だと &lt;code&gt;ValueError: Invalid format string&lt;/code&gt; のエラーが発生しました。&lt;/p&gt;
&lt;p&gt;どうやら Ubuntu と Windows で一部書式が異なるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://teratail.com/questions/361511" target="_blank" rel="noopener"
 &gt;https://teratail.com/questions/361511&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例えば、ゼロパディングをなくしたい場合は、以下のようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Linux の場合&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;%-m&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Windows の場合&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;%#m&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Python の範囲内であればクロスプラットフォームで動作すると思っていたのにこんな罠があるとは。&lt;/p&gt;
&lt;p&gt;上記の例であれば以下のようにすればいいだけですが、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;strftime&lt;/code&gt; を使い場合、大抵もっと複雑な書式で指定すると思うので、どう対応すればいいんでしょうね。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://teratail.com/questions/361511" target="_blank" rel="noopener"
 &gt;https://teratail.com/questions/361511&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Ubuntuでデスクトップにアプリのショートカットを作る（デスクトップエントリ）</title><link>https://blog.ponkotools.com/posts/2022/02/12/ubuntu/</link><pubDate>Sat, 12 Feb 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/02/12/ubuntu/</guid><description>&lt;p&gt;今までやったことなかったのでメモ。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="desktop-ファイルの作成"&gt;&lt;a href="#desktop-%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;.desktop ファイルの作成
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;.desktop&lt;/code&gt; という拡張子でファイルを作成し、デスクトップに配置します。&lt;br&gt;
内容は以下のように記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/usr/bin/env xdg-open
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;Desktop Entry&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;Version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Application
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;Terminal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;Exec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/user/run.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Application Name
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;Comment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Test Application
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;Icon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/user/Pictures/icon.png
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;内容については省略します。&lt;/p&gt;
&lt;h2 id="実行権限の付与"&gt;&lt;a href="#%e5%ae%9f%e8%a1%8c%e6%a8%a9%e9%99%90%e3%81%ae%e4%bb%98%e4%b8%8e" class="header-anchor"&gt;&lt;/a&gt;実行権限の付与
&lt;/h2&gt;&lt;p&gt;このファイルに実行権限を与えます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ chmod &lt;span class="m"&gt;755&lt;/span&gt; test.desktop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;デスクトップでこのファイルをダブルクリックすると、「起動を許可」というメニューがあるので、それを選択します。&lt;br&gt;
すると、アイコンが変わり、ダブルクリックでアプリケーションが起動するようになります。&lt;/p&gt;
&lt;h2 id="起動の許可が表示されないテキストエディタが起動する場合"&gt;&lt;a href="#%e8%b5%b7%e5%8b%95%e3%81%ae%e8%a8%b1%e5%8f%af%e3%81%8c%e8%a1%a8%e7%a4%ba%e3%81%95%e3%82%8c%e3%81%aa%e3%81%84%e3%83%86%e3%82%ad%e3%82%b9%e3%83%88%e3%82%a8%e3%83%87%e3%82%a3%e3%82%bf%e3%81%8c%e8%b5%b7%e5%8b%95%e3%81%99%e3%82%8b%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;起動の許可が表示されない、テキストエディタが起動する場合
&lt;/h2&gt;&lt;p&gt;私の場合の例ですが、&lt;code&gt;.desktop&lt;/code&gt; ファイルの &lt;code&gt;Exec&lt;/code&gt; の項目でシェルスクリプトファイルを指定していた場合に、この状況が発生しました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Exce&lt;/code&gt; で指定しているシェルスクリプトファイルにも実行権限を与えてやると解決しました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://appcel.sblo.jp/article/187826978.html" target="_blank" rel="noopener"
 &gt;http://appcel.sblo.jp/article/187826978.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide] Qt Style Sheet を使って UI のデザインを変更する</title><link>https://blog.ponkotools.com/posts/2022/02/11/pyside/</link><pubDate>Fri, 11 Feb 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/02/11/pyside/</guid><description>&lt;p&gt;UI のデザインを変更したい場合、QSS という、CSS とほぼ同じ構文のスタイルシートを使って変更できます。&lt;/p&gt;
&lt;p&gt;QSS ファイルの拡張子は qss が一般的なようですが、エディタによっては css のほうが便利かもしれません。&lt;br&gt;
QSS 専用のエディタもあるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/takavfx/items/f385bd339d9f352d34cf" target="_blank" rel="noopener"
 &gt;https://qiita.com/takavfx/items/f385bd339d9f352d34cf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;PySide 6.2.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ファイルの読み込みと適用方法"&gt;&lt;a href="#%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ae%e8%aa%ad%e3%81%bf%e8%be%bc%e3%81%bf%e3%81%a8%e9%81%a9%e7%94%a8%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;ファイルの読み込みと適用方法
&lt;/h2&gt;&lt;p&gt;スタイルシートを読み込み、&lt;code&gt;QApplication&lt;/code&gt; に対して &lt;code&gt;setStyleSheet()&lt;/code&gt; で設定するとアプリケーション全体へ適用されるようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;QMainWindow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#444444&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtWidgets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QMainWindow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtCore&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainWindows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QMainWindow&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vbox_layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;button0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vbox_layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignCenter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCentralWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;style.qss&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStyleSheet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MainWindows&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;QSS の書き方については以下のページがとても参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://unpyside.com/2021/05/03/qss-basic/" target="_blank" rel="noopener"
 &gt;https://unpyside.com/2021/05/03/qss-basic/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="特定のウィジェットにのみ適用する方法"&gt;&lt;a href="#%e7%89%b9%e5%ae%9a%e3%81%ae%e3%82%a6%e3%82%a3%e3%82%b8%e3%82%a7%e3%83%83%e3%83%88%e3%81%ab%e3%81%ae%e3%81%bf%e9%81%a9%e7%94%a8%e3%81%99%e3%82%8b%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;特定のウィジェットにのみ適用する方法
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;setObjectName()&lt;/code&gt; で名前を設定し、IDセレクタを使って指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;QMainWindow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#444444&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;/* ボタン全体へ適用 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;QPushButton&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;cyan&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#444444&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;/* button0 のみに適用 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="nn"&gt;button0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;magenta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtWidgets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QMainWindow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtCore&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainWindows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QMainWindow&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vbox_layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;button0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setObjectName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;button0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vbox_layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignCenter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;button1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vbox_layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignCenter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;button2&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vbox_layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignCenter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCentralWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;style.css&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStyleSheet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MainWindows&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="406" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/02/11/pyside/qss.webp" width="542"&gt;&lt;/p&gt;
&lt;h2 id="カスタムウィジェットにスタイルを適用する"&gt;&lt;a href="#%e3%82%ab%e3%82%b9%e3%82%bf%e3%83%a0%e3%82%a6%e3%82%a3%e3%82%b8%e3%82%a7%e3%83%83%e3%83%88%e3%81%ab%e3%82%b9%e3%82%bf%e3%82%a4%e3%83%ab%e3%82%92%e9%81%a9%e7%94%a8%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;カスタムウィジェットにスタイルを適用する
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;QWidget&lt;/code&gt; 継承して作ったカスタムウィジェットに QSS を適用するには、&lt;code&gt;paintEvent&lt;/code&gt; をオーバーライドする必要があります。&lt;br&gt;
これについては以下の記事に書いています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/02/pyside-qss.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/02/pyside-qss.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://unpyside.com/2021/05/03/qss-basic/" target="_blank" rel="noopener"
 &gt;https://unpyside.com/2021/05/03/qss-basic/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kiwamiden.com/how-to-use-qss" target="_blank" rel="noopener"
 &gt;https://kiwamiden.com/how-to-use-qss&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/takavfx/items/f385bd339d9f352d34cf" target="_blank" rel="noopener"
 &gt;https://qiita.com/takavfx/items/f385bd339d9f352d34cf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide] カスタムウィジェットに QSS を適用する</title><link>https://blog.ponkotools.com/posts/2022/02/10/pyside/</link><pubDate>Thu, 10 Feb 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/02/10/pyside/</guid><description>&lt;p&gt;&lt;code&gt;QWidget&lt;/code&gt; を継承して作成したカスタムウィジェットに Qt Style Sheet を適用するには、&lt;code&gt;paintEvent&lt;/code&gt; をオーバーロードする必要があるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://wiki.qt.io/How_to_Change_the_Background_Color_of_QWidget/ja" target="_blank" rel="noopener"
 &gt;https://wiki.qt.io/How_to_Change_the_Background_Color_of_QWidget/ja&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;PySide 6.2.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;CustomWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;cyan&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtWidgets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QMainWindow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QHBoxLayout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QStyleOption&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QStyle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtCore&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtGui&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QPainter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;適当にボタンとラベルと横に並べただけのカスタムウィジェット&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QHBoxLayout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;button&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignCenter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;label&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignCenter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;paintEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;opt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QStyleOption&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;initFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;painter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPainter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drawPrimitive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QStyle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PE_Widget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;painter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainWindows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QMainWindow&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vbox_layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;widget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CustomWidget&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vbox_layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignCenter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCentralWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;style.qss&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setStyleSheet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MainWindows&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="319px" data-flex-grow="133" height="272" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/02/10/pyside/1.webp" width="362"&gt;&lt;/p&gt;
&lt;h2 id="カスタムウィジェット内全体に適用"&gt;&lt;a href="#%e3%82%ab%e3%82%b9%e3%82%bf%e3%83%a0%e3%82%a6%e3%82%a3%e3%82%b8%e3%82%a7%e3%83%83%e3%83%88%e5%86%85%e5%85%a8%e4%bd%93%e3%81%ab%e9%81%a9%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;カスタムウィジェット内全体に適用
&lt;/h2&gt;&lt;p&gt;上記のサンプルでは背景色を適用していますが、ボタンとラベルには適用されていません。&lt;br&gt;
これの対応方法は調査中です。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://wiki.qt.io/How_to_Change_the_Background_Color_of_QWidget/ja" target="_blank" rel="noopener"
 &gt;https://wiki.qt.io/How_to_Change_the_Background_Color_of_QWidget/ja&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide] 'PySide6.QtCore.Signal' object has no attribute 'connect' のエラーが表示される</title><link>https://blog.ponkotools.com/posts/2022/02/07/pyside/</link><pubDate>Mon, 07 Feb 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/02/07/pyside/</guid><description>&lt;p&gt;PySide で、Signal をコンストラクタで初期化すると &lt;code&gt; 'PySide6.QtCore.Signal' object has no attribute 'connect'&lt;/code&gt; のエラーが表示されました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;PySide 6.2.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="エラーとなる例"&gt;&lt;a href="#%e3%82%a8%e3%83%a9%e3%83%bc%e3%81%a8%e3%81%aa%e3%82%8b%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;エラーとなる例
&lt;/h2&gt;&lt;p&gt;例えば、以下のようなコードではエラーになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QObject&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__slot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これについて調べると、以下が見つかりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/36559713/pyside-qtcore-signal-object-has-no-attribute-connect" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/36559713/pyside-qtcore-signal-object-has-no-attribute-connect&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;どうやら、シグナルを使うには以下の必要があるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;クラス内で定義する必要がある（コンストラクタで初期化ではダメ）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;QObject&lt;/code&gt; を継承し、&lt;code&gt;super().__init__()&lt;/code&gt; をコールする必要がある&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="解決方法"&gt;&lt;a href="#%e8%a7%a3%e6%b1%ba%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;解決方法
&lt;/h2&gt;&lt;p&gt;以下のようにすると上手く動作します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QObject&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__slot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コンストラクタで &lt;code&gt;for&lt;/code&gt; を使ってシグナルを一気に作成したり発報したりしたかったのですが、できないんですかね？&lt;/p&gt;
&lt;h2 id="どうしても-for-で楽がしたい"&gt;&lt;a href="#%e3%81%a9%e3%81%86%e3%81%97%e3%81%a6%e3%82%82-for-%e3%81%a7%e6%a5%bd%e3%81%8c%e3%81%97%e3%81%9f%e3%81%84" class="header-anchor"&gt;&lt;/a&gt;どうしても for で楽がしたい
&lt;/h2&gt;&lt;p&gt;苦肉の策で、以下のようなコードを思いつきました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="ne"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QObject&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;signal_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;signal_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__dict__&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;signal_a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__slot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;emit_sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signal_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;signal_name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__dict__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__dict__&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;signal_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;シグナルの宣言は個別に行う必要がありますが、&lt;code&gt;self.__dict__&lt;/code&gt; でインスタンス変数の一覧を取得し、その中からシグナル名でシグナルを探してきます。&lt;br&gt;
微妙ですね。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/36559713/pyside-qtcore-signal-object-has-no-attribute-connect" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/36559713/pyside-qtcore-signal-object-has-no-attribute-connect&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide] ボタンにフォーカスがある場合の点線を消す</title><link>https://blog.ponkotools.com/posts/2022/02/02/pyside/</link><pubDate>Wed, 02 Feb 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/02/02/pyside/</guid><description>&lt;p&gt;CSS を使って以下を指定すれば消せます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;focus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/17280056/qt-css-decoration-on-focus" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/17280056/qt-css-decoration-on-focus&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide] QStackedLayout で Alignment を設定したい</title><link>https://blog.ponkotools.com/posts/2022/02/01/pyside/</link><pubDate>Tue, 01 Feb 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/02/01/pyside/</guid><description>&lt;p&gt;&lt;code&gt;QStackedLayout&lt;/code&gt; の &lt;code&gt;addWidget&lt;/code&gt; では &lt;code&gt;alignment&lt;/code&gt; を指定できません。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;QVBoxLayout&lt;/code&gt; や &lt;code&gt;QHBoxLayout&lt;/code&gt; のように alignment を指定したい場合はどうすれいいのか？&lt;br&gt;
ということでググってみたものの情報が少なく、参考になりそうなのは以下くらい。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/5459602/how-to-center-widget-inside-qstackedlayout" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/5459602/how-to-center-widget-inside-qstackedlayout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/66089492/how-to-add-the-layout-to-qstackedlayout" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/66089492/how-to-add-the-layout-to-qstackedlayout&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;こういうこと？なんか違う気がする・・・。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtWidgets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtCore&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtCharts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainWindows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# コンテナを親として QVBoxLayout を作成（つまり、コンテナ配下に QVBoxLayout を作成）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vbox_layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vbox_layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;test1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignCenter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stacked_layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QStackedLayout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stacked_layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stacked_layout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MainWindows&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一応表示は正しいんですけどね。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="406" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/02/01/pyside/01.webp" width="542"&gt;&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/5459602/how-to-center-widget-inside-qstackedlayout" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/5459602/how-to-center-widget-inside-qstackedlayout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/66089492/how-to-add-the-layout-to-qstackedlayout" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/66089492/how-to-add-the-layout-to-qstackedlayout&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide] for 文でシグナルの接続にラムダ式を使う場合の注意</title><link>https://blog.ponkotools.com/posts/2022/01/31/pyside/</link><pubDate>Mon, 31 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/31/pyside/</guid><description>&lt;p&gt;for ループでウィジェットを動的に作成する際、シグナルとの接続でラムダ式を使う場合には注意が必要です。&lt;/p&gt;
&lt;p&gt;例えば、以下のコードはラムダ式を使っていますが、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Button&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clicked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Button&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; clicked&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この場合、どのボタンを押しても &lt;code&gt;Button4 clicked&lt;/code&gt; と出力されます。&lt;br&gt;
ラムダ式は遅延評価のためです。&lt;/p&gt;
&lt;p&gt;これについては以下の記事を参考にしてください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/01/python-for.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/01/python-for.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;じゃあデフォルト引数を与えて即時評価してやろう以下のように変更すると、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Button&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clicked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Button&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; clicked&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今度は &lt;code&gt;ButtonFalse clicked&lt;/code&gt; と出力されてしまいました。&lt;br&gt;
&lt;code&gt;QPushButton&lt;/code&gt; の &lt;code&gt;clicked&lt;/code&gt; シグナルは、ボタンの状態を引数で渡してくるそうなので、デフォルト引数が bool 値で上書きされたためです。&lt;br&gt;
かと言って、引数の数を増やすとエラーになります。&lt;/p&gt;
&lt;p&gt;なので、この場合ラムダ式は使えず、&lt;code&gt;functools.partial&lt;/code&gt; を使うしかありません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Button&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clicked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__clicked&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下、動作確認用のコードです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;functools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtWidgets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QMainWindow&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vbox_layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Button&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clicked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__clicked&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vbox_layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;widget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vbox_layout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCentralWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__clicked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Button&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; clicked&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;main_window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;main_window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>[PySide] QChart のグラフに Tooltip を追加する</title><link>https://blog.ponkotools.com/posts/2022/01/28/pyside/</link><pubDate>Fri, 28 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/28/pyside/</guid><description>&lt;p&gt;グラフにマウスオーバーしたときにツールチップを表示するサンプルです。&lt;/p&gt;
&lt;p&gt;とりあえず &lt;code&gt;QToolTip&lt;/code&gt; を使って簡単に実装してみました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qtforpython/PySide6/QtWidgets/QToolTip.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qtforpython/PySide6/QtWidgets/QToolTip.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;他には以下のサンプルとかも見つかりましたが、ちょっと複雑なので・・・。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qtforpython-6/examples/example_charts__callout.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qtforpython-6/examples/example_charts__callout.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;PySide 6.2.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプル"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;サンプル
&lt;/h2&gt;&lt;p&gt;以前の記事をベースに作成してみました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/01/pyside-qchart.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/01/pyside-qchart.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;QBarSeries&lt;/code&gt; と &lt;code&gt;QBarSet&lt;/code&gt; のどちらのマウスオーバーでツールチップを表示するかはお好みで。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtWidgets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtCore&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtCharts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtGui&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QPainter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QCursor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BarChartSample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QChartView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;__categories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Jan&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Feb&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Mar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Apr&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;May&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Jun&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;__samples&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Hoge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Piyo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Fuga&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Foo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Bar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;series&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QBarSeries&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#series = QStackedBarSeries()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__samples&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;barset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QBarSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#barset.hovered.connect(lambda state,index, x=key: self.__barset_hovered(x, index, state)) # 即時評価するため key を x に代入&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;barset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;barset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hovered&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__barseries_hovered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QChart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addSeries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Barchart example&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setAnimationOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QChart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SeriesAnimations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;axis_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QBarCategoryAxis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;axis_x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__categories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addAxis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;axis_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignBottom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attachAxis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;axis_x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;axis_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QValueAxis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addAxis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;axis_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignLeft&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attachAxis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;axis_y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setAlignment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignBottom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setRenderHint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QPainter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Antialiasing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setChart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__tooltip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QToolTip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__barseries_hovered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;barsetseries hovered, state=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, index=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;texts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__samples&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;texts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__tooltip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;showText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QCursor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texts&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__tooltip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hideText&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__barset_hovered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; hovered index=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, category=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__categories&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;, state=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__tooltip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;showText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QCursor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__samples&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__tooltip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hideText&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainWindows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QMainWindow&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;barchart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BarChartSample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCentralWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;barchart&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MainWindows&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;720&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;480&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="359px" data-flex-grow="149" height="478" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/01/28/pyside/01.webp" width="716"&gt;&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qtforpython/PySide6/QtWidgets/QToolTip.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qtforpython/PySide6/QtWidgets/QToolTip.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qtforpython-6/examples/example_charts__callout.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qtforpython-6/examples/example_charts__callout.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://fereria.github.io/reincarnation_tech/11_PySide/02_Tips/03_custom_tooltip/" target="_blank" rel="noopener"
 &gt;https://fereria.github.io/reincarnation_tech/11_PySide/02_Tips/03_custom_tooltip/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide6] ui ファイルが読み込めないので、py ファイルにコンバートして読み込む</title><link>https://blog.ponkotools.com/posts/2022/01/27/pyside/</link><pubDate>Thu, 27 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/27/pyside/</guid><description>&lt;p&gt;PySide2 では読み込めていた ui ファイルが、PySide6 に移行後読み込めなくなってしまいました。&lt;/p&gt;
&lt;p&gt;PySide2 では以下のようなコードで ui ファイルを読み込んでいました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ui&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QUiLoader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./form.ui&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;しかし、PySide6 で同じように ui ファイルを読み込もうとすると、以下のエラーが表示されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;qt.pysideplugin: Environment variable PYSIDE_DESIGNER_PLUGINS is not set, bailing out.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;qt.pysideplugin: No instance of QPyDesignerCustomWidgetCollection was found.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;環境変数 &lt;code&gt;PYSIDE_DESIGNER_PLUGINS&lt;/code&gt; を設定すれば良さそうですが、ググっても解決方法がわかりませんでした。&lt;/p&gt;
&lt;p&gt;代わりに、ui ファイルを py ファイルにコンバートする方法がたくさん見つかったので、これで対応しました。&lt;br&gt;
（一手間増えて面倒ですが・・・）&lt;/p&gt;
&lt;h2 id="ui-ファイルから-py-ファイルへのコンバート"&gt;&lt;a href="#ui-%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%8b%e3%82%89-py-%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%b8%e3%81%ae%e3%82%b3%e3%83%b3%e3%83%90%e3%83%bc%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;ui ファイルから py ファイルへのコンバート
&lt;/h2&gt;&lt;p&gt;以下のコマンドでコンバートできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pyside6-uic form.ui -o ui_form.py
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="コンバートした-py-ファイルの読み込み方法"&gt;&lt;a href="#%e3%82%b3%e3%83%b3%e3%83%90%e3%83%bc%e3%83%88%e3%81%97%e3%81%9f-py-%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ae%e8%aa%ad%e3%81%bf%e8%be%bc%e3%81%bf%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;コンバートした py ファイルの読み込み方法
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QMainWindow&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ui&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UI_Form&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setupUi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.youtube.com/watch?v=3gTh4_l40WI" target="_blank" rel="noopener"
 &gt;https://www.youtube.com/watch?v=3gTh4_l40WI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/ShimantoAkira/items/9d19baa5f3e0682835e3" target="_blank" rel="noopener"
 &gt;https://qiita.com/ShimantoAkira/items/9d19baa5f3e0682835e3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/68528717/environment-variable-pyside-designer-plugins-is-not-set-bailing-out" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/68528717/environment-variable-pyside-designer-plugins-is-not-set-bailing-out&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qtforpython/tutorials/basictutorial/uifiles.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qtforpython/tutorials/basictutorial/uifiles.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide] QChart で棒グラフを作成</title><link>https://blog.ponkotools.com/posts/2022/01/26/pyside/</link><pubDate>Wed, 26 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/26/pyside/</guid><description>&lt;p&gt;QChart を使って棒グラフを作成してみました。&lt;/p&gt;
&lt;p&gt;公式のサンプルは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qtforpython/examples/example_charts__barchart.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qtforpython/examples/example_charts__barchart.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;基本的な挙動は上記が理解しやすいと思いますが、実際にはループで処理することが多いと思うので、少し変更してみました。
pandas などと組み合わせれば大量のデータであっても効率的にグラフを作成できると思います。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;PySide 6.2.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプル"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;サンプル
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtWidgets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtCore&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtCharts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide6.QtGui&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QPainter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QCursor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BarChartSample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QChartView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;__categories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Jan&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Feb&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Mar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Apr&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;May&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Jun&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;__samples&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Hoge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Piyo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Fuga&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Foo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Bar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;series&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QBarSeries&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#series = QStackedBarSeries()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__samples&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;barset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QBarSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;barset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;barset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QChart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addSeries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Barchart example&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setAnimationOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QChart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SeriesAnimations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;axis_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QBarCategoryAxis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;axis_x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__categories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addAxis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;axis_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignBottom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attachAxis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;axis_x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;axis_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QValueAxis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addAxis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;axis_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignLeft&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attachAxis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;axis_y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setAlignment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlignBottom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setRenderHint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QPainter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Antialiasing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setChart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainWindows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QMainWindow&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;barchart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BarChartSample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCentralWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;barchart&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MainWindows&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;720&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;480&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="478" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/01/26/pyside/01.webp" width="718"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;QBarSeries&lt;/code&gt; を &lt;code&gt;QStackedBarSeries&lt;/code&gt; に変更すれば積み上げグラフになります。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="360px" data-flex-grow="150" height="478" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2022/01/26/pyside/02.webp" width="718"&gt;&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qtforpython/examples/example_charts__barchart.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qtforpython/examples/example_charts__barchart.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qt-5/qbarset.html#append" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qt-5/qbarset.html#append&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://bitwalk.blogspot.com/2021/07/qt-for-python-3.html" target="_blank" rel="noopener"
 &gt;https://bitwalk.blogspot.com/2021/07/qt-for-python-3.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qt-5/qchart.html#ChartTheme-enum" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qt-5/qchart.html#ChartTheme-enum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://runebook.dev/ja/docs/qt/qbarset" target="_blank" rel="noopener"
 &gt;https://runebook.dev/ja/docs/qt/qbarset&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://runebook.dev/ja/docs/qt/qabstractbarseries#clicked" target="_blank" rel="noopener"
 &gt;https://runebook.dev/ja/docs/qt/qabstractbarseries#clicked&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.qt.io/qt-5/qstackedbarseries.html" target="_blank" rel="noopener"
 &gt;https://doc.qt.io/qt-5/qstackedbarseries.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] 時刻のみを扱う型</title><link>https://blog.ponkotools.com/posts/2022/01/24/python/</link><pubDate>Mon, 24 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/24/python/</guid><description>&lt;p&gt;&lt;code&gt;datetime.time&lt;/code&gt; 型が時刻を扱う型になります。&lt;/p&gt;
&lt;p&gt;Python には &lt;code&gt;time&lt;/code&gt; というモジュールがあるのでややこしいですが、&lt;code&gt;time&lt;/code&gt; モジュールのことではなく、&lt;code&gt;datetime&lt;/code&gt; モジュールに含まれる &lt;code&gt;datetime.time&lt;/code&gt; という型です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;59&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;59&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;class &amp;#39;datetime.time&amp;#39;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;23:59:59.000999
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;time&lt;/code&gt; モジュールを一緒にインポートしている場合は特にややこしいので、以下のようにエイリアスを設定しておいたほうがわかりやすいかもしれません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;datetime_time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime_time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;59&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;59&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="datetime-型から時刻のみを取り出す"&gt;&lt;a href="#datetime-%e5%9e%8b%e3%81%8b%e3%82%89%e6%99%82%e5%88%bb%e3%81%ae%e3%81%bf%e3%82%92%e5%8f%96%e3%82%8a%e5%87%ba%e3%81%99" class="header-anchor"&gt;&lt;/a&gt;datetime 型から時刻のみを取り出す
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;time()&lt;/code&gt; メソッドで取り出せます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-01-07 13:26:46.826983
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;class &amp;#39;datetime.time&amp;#39;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;13:26:46.826983
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>[Python] for文の中のラムダ式でループ変数を参照する場合は評価のタイミングに注意</title><link>https://blog.ponkotools.com/posts/2022/01/23/python/</link><pubDate>Sun, 23 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/23/python/</guid><description>&lt;p&gt;Python に限らないと思いますが、知らないとハマることになるやつですね。&lt;/p&gt;
&lt;p&gt;例えば、以下のように関数を登録して後から実行した場合、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;funcs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;期待する動作は 0～4 が順に出力されることですが、上記だと全て &lt;code&gt;4&lt;/code&gt; が出力されます。&lt;/p&gt;
&lt;p&gt;ここのラムダ式は遅延評価、関数が呼ばれたときに初めて評価されます。&lt;br&gt;
従って、関数が実行されたときは既にループが終わった後であり、その時には &lt;code&gt;i&lt;/code&gt; は &lt;code&gt;4&lt;/code&gt; になっているため、常に &lt;code&gt;4&lt;/code&gt; と出力されてしまいます。&lt;/p&gt;
&lt;p&gt;解決方法として、私が知っている範囲では以下の２パターンがあります。&lt;/p&gt;
&lt;h2 id="デフォルト引数で対応"&gt;&lt;a href="#%e3%83%87%e3%83%95%e3%82%a9%e3%83%ab%e3%83%88%e5%bc%95%e6%95%b0%e3%81%a7%e5%af%be%e5%bf%9c" class="header-anchor"&gt;&lt;/a&gt;デフォルト引数で対応
&lt;/h2&gt;&lt;p&gt;以下のようにラムダ式にデフォルト引数を与えてやります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;funcs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;x=i&lt;/code&gt; とすることで即時評価され、期待した出力となります。&lt;/p&gt;
&lt;p&gt;しかし、以下のように実行時に引数を与えると、与えられた引数で上書きされてしまいます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;funcs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次の方法だとこの問題も回避できます。&lt;/p&gt;
&lt;h2 id="functoolspartial-を使う"&gt;&lt;a href="#functoolspartial-%e3%82%92%e4%bd%bf%e3%81%86" class="header-anchor"&gt;&lt;/a&gt;functools.partial を使う
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;functools.partial()&lt;/code&gt; は 引数を部分的に適用（固定化？）した関数を生成する関数です。&lt;br&gt;
以下のように書くことで期待した出力となります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;functools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;funcs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この場合、実行時に引数を与えるとエラーになります。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://tm8r.hateblo.jp/entry/2020/03/11/140252" target="_blank" rel="noopener"
 &gt;https://tm8r.hateblo.jp/entry/2020/03/11/140252&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://tablogweb.wordpress.com/2019/08/26/python%E3%81%AElambda%E5%88%B6%E9%99%90/" target="_blank" rel="noopener"
 &gt;https://tablogweb.wordpress.com/2019/08/26/python%E3%81%AElambda%E5%88%B6%E9%99%90/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>WSL2 の Ubuntu で Docker を動かす</title><link>https://blog.ponkotools.com/posts/2022/01/20/wsl-ubuntu-docker/</link><pubDate>Thu, 20 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/20/wsl-ubuntu-docker/</guid><description>&lt;p&gt;DockerDesktop が有償になったので、WSL2 の Ubuntu に Docker をインストールして動かすようにしてみました、&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Windows 10&lt;/li&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;WSL2 および Ubuntu はインストール済みの前提です。&lt;br&gt;
以下のページに書いてあるので、まだの場合は参考にしてください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/01/wsl2.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/01/wsl2.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="プロキシ設定"&gt;&lt;a href="#%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;プロキシ設定
&lt;/h2&gt;&lt;p&gt;環境に応じてプロキシの設定を行っておきます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.bashrc&lt;/code&gt; をエディタで開き、最後に以下を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;http_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://example.com:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;https_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://example.com:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;no_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;任意のIPアドレス
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="apt-のプロキシ設定"&gt;&lt;a href="#apt-%e3%81%ae%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;apt のプロキシ設定
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;/etc/apt/apt.conf&lt;/code&gt; を作成して以下のように記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Acquire::http::proxy &lt;span class="s2"&gt;&amp;#34;http://example.com:8080/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Acquire::https::proxy &lt;span class="s2"&gt;&amp;#34;https://example.com:8080/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="docker-のインストール"&gt;&lt;a href="#docker-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;Docker のインストール
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://docs.docker.com/engine/install/ubuntu/" target="_blank" rel="noopener"
 &gt;公式ドキュメント&lt;/a&gt;に沿ってインストールします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get remove docker docker-engine docker.io containerd runc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg &lt;span class="p"&gt;|&lt;/span&gt; sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;deb [arch=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dpkg --print-architecture&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;lsb_release -cs&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ユーザーを-docker-グループに追加"&gt;&lt;a href="#%e3%83%a6%e3%83%bc%e3%82%b6%e3%83%bc%e3%82%92-docker-%e3%82%b0%e3%83%ab%e3%83%bc%e3%83%97%e3%81%ab%e8%bf%bd%e5%8a%a0" class="header-anchor"&gt;&lt;/a&gt;ユーザーを docker グループに追加
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo gpasswd -a &lt;span class="k"&gt;$(&lt;/span&gt;whoami&lt;span class="k"&gt;)&lt;/span&gt; docker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで docker コマンド実行時に sudo が不要になります。&lt;/p&gt;
&lt;h3 id="docker-のプロキシ設定"&gt;&lt;a href="#docker-%e3%81%ae%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;docker のプロキシ設定
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;/etc/default/docker&lt;/code&gt; をエディタで開いて以下を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;http_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://example.com:8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;https_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://example.com:8080
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、&lt;code&gt;~/.docker/config.json&lt;/code&gt; に以下を記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;proxies&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;httpProxy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;http://example.com:8080&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;httpsProxy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;http://example.com:8080&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="docker-デーモンの起動"&gt;&lt;a href="#docker-%e3%83%87%e3%83%bc%e3%83%a2%e3%83%b3%e3%81%ae%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;docker デーモンの起動
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo service docker start
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="動作確認"&gt;&lt;a href="#%e5%8b%95%e4%bd%9c%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;動作確認
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker info
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run hello-world
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;すると、私の場合以下のエラーが表示されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;docker デーモンが起動しているか確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo service docker status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* Docker is not running
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;原因がわからず悩んでいたところ、以下の記事を見つけました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/neight0903/items/ef0e2170b712b194c3fc" target="_blank" rel="noopener"
 &gt;https://qiita.com/neight0903/items/ef0e2170b712b194c3fc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;私の場合、既に DockerDesktop はアンインストールしていました。&lt;br&gt;
もともとは DockerDesktop と WSL2 を使って動かしていたのですが、今回 DockerDesktop なしで動くようにしようとしているところで、
DockerDesktop だけでなく WSL2 も一度アンインストールして最初からやり直すと上手く行きました。&lt;/p&gt;
&lt;h2 id="docker-デーモンの自動起動"&gt;&lt;a href="#docker-%e3%83%87%e3%83%bc%e3%83%a2%e3%83%b3%e3%81%ae%e8%87%aa%e5%8b%95%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;docker デーモンの自動起動
&lt;/h2&gt;&lt;p&gt;このままでは WSL を起動する度に docker デーモンを手動で起動する必要がありますが、以下のページに自動起動させる方法があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://zenn.dev/taiga533/articles/11f1b21ef4a5ff" target="_blank" rel="noopener"
 &gt;https://zenn.dev/taiga533/articles/11f1b21ef4a5ff&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/ko-zi/items/949d358163bbbad5a91e" target="_blank" rel="noopener"
 &gt;https://qiita.com/ko-zi/items/949d358163bbbad5a91e&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://zukucode.com/2021/11/wsl2-docker-startup.html" target="_blank" rel="noopener"
 &gt;https://zukucode.com/2021/11/wsl2-docker-startup.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;まずは &lt;code&gt;sudo service docker start&lt;/code&gt; をパスワードなしで実行できるように設定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo visudo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ユーザー名 ALL=(ALL:ALL) NOPASSWD: /usr/sbin/service docker start
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとは .bashrc に以下を追記します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nano .bashrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;if [ $(service docker status | awk &amp;#39;{print $4}&amp;#39;) = &amp;#34;not&amp;#34; ]; then
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sudo service docker start &amp;gt; /dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fi
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="windows-と-wsl2-のポートフォワーディングの設定"&gt;&lt;a href="#windows-%e3%81%a8-wsl2-%e3%81%ae%e3%83%9d%e3%83%bc%e3%83%88%e3%83%95%e3%82%a9%e3%83%af%e3%83%bc%e3%83%87%e3%82%a3%e3%83%b3%e3%82%b0%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Windows と WSL2 のポートフォワーディングの設定
&lt;/h2&gt;&lt;p&gt;WSL2 上の Docker コンテナに外部からアクセスしたい場合、Windows と WSL2 のポートフォワーディングの設定が必要です。&lt;br&gt;
詳細は以下の記事を参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/07/wsl2-docker.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/07/wsl2-docker.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://zenn.dev/taiga533/articles/11f1b21ef4a5ff" target="_blank" rel="noopener"
 &gt;https://zenn.dev/taiga533/articles/11f1b21ef4a5ff&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/neight0903/items/ef0e2170b712b194c3fc" target="_blank" rel="noopener"
 &gt;https://qiita.com/neight0903/items/ef0e2170b712b194c3fc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] groupby の使い方</title><link>https://blog.ponkotools.com/posts/2022/01/19/python/</link><pubDate>Wed, 19 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/19/python/</guid><description>&lt;p&gt;C# の Linq にある GroupBy と同じことを Python でやるにはどうしたらいいのかと思い調べたら、&lt;code&gt;itertools&lt;/code&gt; モジュールに &lt;code&gt;groupby&lt;/code&gt; というクラスがありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.python.org/ja/3/library/itertools.html#itertools.groupby" target="_blank" rel="noopener"
 &gt;https://docs.python.org/ja/3/library/itertools.html#itertools.groupby&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプル"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;サンプル
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;itertools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;groupby&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サンプルデータ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;members&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;country&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Japan&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;sex&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;male&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;country&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;America&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;sex&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;female&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;country&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;China&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;sex&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;male&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;C&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;country&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Japan&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;sex&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;female&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;D&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;country&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;America&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;sex&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;male&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;E&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;country&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;China&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;sex&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;female&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;F&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# groupby を使うには、まずはグルーピングしたいキーでソートしておく必要がある&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;members&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;country&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ソートした上で、キーを指定してグループ化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;grouped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;members&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;country&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# グループ化した内容を表示して確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;grouped_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;grouped&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;member_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# group はイテレーターなので、リストに変換&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;grouped_list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;key&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;members&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;member_list&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grouped_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;key&amp;#34;: &amp;#34;America&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;members&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;country&amp;#34;: &amp;#34;America&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;sex&amp;#34;: &amp;#34;female&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;name&amp;#34;: &amp;#34;B&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;country&amp;#34;: &amp;#34;America&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;sex&amp;#34;: &amp;#34;male&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;name&amp;#34;: &amp;#34;E&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;key&amp;#34;: &amp;#34;China&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;members&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;country&amp;#34;: &amp;#34;China&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;sex&amp;#34;: &amp;#34;male&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;name&amp;#34;: &amp;#34;C&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;country&amp;#34;: &amp;#34;China&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;sex&amp;#34;: &amp;#34;female&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;name&amp;#34;: &amp;#34;F&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;key&amp;#34;: &amp;#34;Japan&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;members&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;country&amp;#34;: &amp;#34;Japan&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;sex&amp;#34;: &amp;#34;male&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;name&amp;#34;: &amp;#34;A&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;country&amp;#34;: &amp;#34;Japan&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;sex&amp;#34;: &amp;#34;female&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;name&amp;#34;: &amp;#34;D&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.python.org/ja/3/library/itertools.html#itertools.groupby" target="_blank" rel="noopener"
 &gt;https://docs.python.org/ja/3/library/itertools.html#itertools.groupby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://techblog.recochoku.jp/5117" target="_blank" rel="noopener"
 &gt;https://techblog.recochoku.jp/5117&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] 月初日、月末日、翌月の月初日の取得</title><link>https://blog.ponkotools.com/posts/2022/01/18/python/</link><pubDate>Tue, 18 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/18/python/</guid><description>&lt;p&gt;日時を扱っていると月初日や月末日を取得したいということもあるので、そのやり方です。&lt;/p&gt;
&lt;p&gt;やり方はいろいろあるかもしれませんが、あくまで一例ということで。&lt;/p&gt;
&lt;h2 id="月初日"&gt;&lt;a href="#%e6%9c%88%e5%88%9d%e6%97%a5" class="header-anchor"&gt;&lt;/a&gt;月初日
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;first_dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;first_dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-01-17 15:55:25.492664
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-01-01 15:55:25.492664
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-01-01 00:00:00
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;時刻を保持したい場合は &lt;code&gt;replace&lt;/code&gt; で日だけ置き換えればOKです。&lt;br&gt;
時刻をクリアしたい場合は年月日を指定して新たに datetime を作成すればOKです。&lt;/p&gt;
&lt;h2 id="月末日"&gt;&lt;a href="#%e6%9c%88%e6%9c%ab%e6%97%a5" class="header-anchor"&gt;&lt;/a&gt;月末日
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;calendar&lt;/code&gt; モジュールを使えば簡単にできます。&lt;br&gt;
&lt;code&gt;monthrange&lt;/code&gt; は指定した年月の初日の曜日と日数を返してくれます。&lt;br&gt;
これを使って月初日と同じように取得できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;calendar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;day_of_week&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calendar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;monthrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;last_dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;last_day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last_dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;last_dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last_dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-01-17 16:04:31.007994
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-01-31 16:04:31.008065
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-01-31 00:00:00
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="翌月の月初日"&gt;&lt;a href="#%e7%bf%8c%e6%9c%88%e3%81%ae%e6%9c%88%e5%88%9d%e6%97%a5" class="header-anchor"&gt;&lt;/a&gt;翌月の月初日
&lt;/h2&gt;&lt;p&gt;やり方としては以下の２通りがあります。&lt;/p&gt;
&lt;h3 id="calendar-と-timedelta-を使う方法"&gt;&lt;a href="#calendar-%e3%81%a8-timedelta-%e3%82%92%e4%bd%bf%e3%81%86%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;calendar と timedelta を使う方法
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;calendar.monthrange&lt;/code&gt; を使えば前述した方法で月末日が取得できるので、ここから &lt;code&gt;timedelta&lt;/code&gt; を使って一日足してやれば、翌月の月初日が取得できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from datetime import datetime, timedelta
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;import calendar
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dt = datetime.now()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(dt)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;day_of_week, last_day = calendar.monthrange(dt.year, dt.month)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;next_first_dt = dt.replace(day=last_day) + timedelta(days=1)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(next_first_dt)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;next_first_dt = datetime(dt.year, dt.month, last_day) + timedelta(days=1)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(next_first_dt)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-01-17 16:37:09.969484
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-02-01 16:37:09.969484
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-02-01 00:00:00
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="dateutilrelativedelta-を使う方法"&gt;&lt;a href="#dateutilrelativedelta-%e3%82%92%e4%bd%bf%e3%81%86%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;dateutil.relativedelta を使う方法
&lt;/h3&gt;&lt;p&gt;まず &lt;code&gt;python-dateutil&lt;/code&gt; をインストールする必要があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pip install python-dateutil
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;dateutil.relativedelta&lt;/code&gt; を使えば一ヶ月後の日時が取得できるので、そこから前述した方法と同じように月初日が取得できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;dateutil.relativedelta&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;relativedelta&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;next_dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;relativedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;months&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;next_first_dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next_dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next_first_dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;next_first_dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next_dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next_dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next_first_dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-01-17 16:42:25.298845
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-02-01 16:42:25.298845
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-02-01 00:00:00
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="所感"&gt;&lt;a href="#%e6%89%80%e6%84%9f" class="header-anchor"&gt;&lt;/a&gt;所感
&lt;/h3&gt;&lt;p&gt;標準モジュールだけで実装したい場合は &lt;code&gt;calendar&lt;/code&gt; と &lt;code&gt;timedelta&lt;/code&gt; を使って実装すればいいですが、翌々月とか数ヶ月後とかも扱うのであれば &lt;code&gt;dateutil.relativedelta&lt;/code&gt; を使ったほうが楽だと思いました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/dkugi/items/8c32cc481b365c277ec2" target="_blank" rel="noopener"
 &gt;https://qiita.com/dkugi/items/8c32cc481b365c277ec2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/wakanayoshizawa/items/5f3063bc89ab39183cb6" target="_blank" rel="noopener"
 &gt;https://qiita.com/wakanayoshizawa/items/5f3063bc89ab39183cb6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://note.nkmk.me/python-datetime-first-last-date-last-week/" target="_blank" rel="noopener"
 &gt;https://note.nkmk.me/python-datetime-first-last-date-last-week/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PySide] ダイアログの作成</title><link>https://blog.ponkotools.com/posts/2022/01/17/pyside/</link><pubDate>Mon, 17 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/17/pyside/</guid><description>&lt;p&gt;QDialog を使ってダイアログを作るサンプルです。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;PySide 6.2.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;p&gt;ここでは、ボタンを押したときにダイアログを表示してみました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PySide2.QtWidgets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyDialog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QDialog&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ベース・クラスの初期化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyDialog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ウィンドウタイトルを設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setWindowTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;My Dialog&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ラベルの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;こんにちは。&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 縦方向レイアウトを使って配置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QMainWindow&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ボタンの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Push!!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clicked&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__clicked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="c1"&gt;# ボタンが押された時の処理を設定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCentralWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__clicked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dialog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyDialog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dialog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;main_window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MainWindow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;main_window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.programcreek.com/python/example/115469/PySide2.QtWidgets.QDialog" target="_blank" rel="noopener"
 &gt;https://www.programcreek.com/python/example/115469/PySide2.QtWidgets.QDialog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>WSL2 で GUI を表示する</title><link>https://blog.ponkotools.com/posts/2022/01/16/wsl/</link><pubDate>Sun, 16 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/16/wsl/</guid><description>&lt;p&gt;Windows に Xサーバーをインストールし、WSL2 上で実行した GUI アプリを表示できるようにする方法です。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Windows 10&lt;/li&gt;
&lt;li&gt;WSL2:Ubuntu 20.04&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="xサーバーのインストール"&gt;&lt;a href="#x%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;Xサーバーのインストール
&lt;/h2&gt;&lt;p&gt;Windows にXサーバーをインストールします。
私は以下のページを参考に &lt;code&gt;VcXsrv&lt;/code&gt; を入れました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://rin-ka.net/windows-x-server/" target="_blank" rel="noopener"
 &gt;https://rin-ka.net/windows-x-server/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;他には &lt;code&gt;MobaXterm&lt;/code&gt; も良さそうですね。&lt;/p&gt;
&lt;p&gt;あとは、ファイアウォールの設定も許可する必要があります。&lt;br&gt;
設定完了後、&lt;code&gt;VcXsrv&lt;/code&gt; 起動時に許可を求める画面が表示されるので、そこで全て許可しました。&lt;/p&gt;
&lt;h2 id="wsl2-側の設定"&gt;&lt;a href="#wsl2-%e5%81%b4%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;WSL2 側の設定
&lt;/h2&gt;&lt;p&gt;Linux ではおなじみの &lt;code&gt;export DISPLAY=:0&lt;/code&gt; では駄目なようで、IPアドレスを指定する必要があるみたいです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://odaryo.hatenablog.com/entry/2020/01/08/114846" target="_blank" rel="noopener"
 &gt;https://odaryo.hatenablog.com/entry/2020/01/08/114846&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下のようにすれば IP アドレスを読み込んで環境変数をセットしてくれるようです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;DISPLAY&lt;/span&gt;&lt;span class="o"&gt;=$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;resolv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;grep&lt;/span&gt; &lt;span class="n"&gt;nameserver&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これを毎回入力するのも面倒なので、&lt;code&gt;.bashrc&lt;/code&gt; に書いておけば、WSL2 起動時に自動でセットされるようです。&lt;/p&gt;
&lt;h2 id="動作確認"&gt;&lt;a href="#%e5%8b%95%e4%bd%9c%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;動作確認
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;VcXsrv&lt;/code&gt; を、&lt;code&gt;Disable access control&lt;/code&gt; にチェックを入れて起動し、WSL2 上で以下のコマンドを実行して確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ xeyes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="vscode--remote-containers-を使う場合"&gt;&lt;a href="#vscode--remote-containers-%e3%82%92%e4%bd%bf%e3%81%86%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;VSCode + Remote-Containers を使う場合
&lt;/h2&gt;&lt;p&gt;WSL2 上で VSCode を実行して Remote-Containers を使う場合、WSL2 の &lt;code&gt;DISPLAY&lt;/code&gt; の値を Retemo-Containers 側にも引き継げば、Retemo-Containers でも GUI の表示が可能です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/y-na-biz/items/af0137532e6e22802f25#%E5%8F%82%E8%80%83devcontainerjson%E8%A8%AD%E5%AE%9A%E4%B8%80%E8%A6%A7" target="_blank" rel="noopener"
 &gt;https://qiita.com/y-na-biz/items/af0137532e6e22802f25#%E5%8F%82%E8%80%83devcontainerjson%E8%A8%AD%E5%AE%9A%E4%B8%80%E8%A6%A7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&amp;#34;runArgs&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&amp;#34;-e&amp;#34;, &amp;#34;DISPLAY=${env:DISPLAY}&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	],
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&amp;#34;mounts&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&amp;#34;source=/tmp/.X11-unix/,target=/tmp/.X11-unix/,type=bind&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	],
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://rin-ka.net/windows-x-server/" target="_blank" rel="noopener"
 &gt;https://rin-ka.net/windows-x-server/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://islandcnt.exblog.jp/240399231/" target="_blank" rel="noopener"
 &gt;https://islandcnt.exblog.jp/240399231/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://odaryo.hatenablog.com/entry/2020/01/08/114846" target="_blank" rel="noopener"
 &gt;https://odaryo.hatenablog.com/entry/2020/01/08/114846&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/y-na-biz/items/af0137532e6e22802f25#%E5%8F%82%E8%80%83devcontainerjson%E8%A8%AD%E5%AE%9A%E4%B8%80%E8%A6%A7" target="_blank" rel="noopener"
 &gt;https://qiita.com/y-na-biz/items/af0137532e6e22802f25#%E5%8F%82%E8%80%83devcontainerjson%E8%A8%AD%E5%AE%9A%E4%B8%80%E8%A6%A7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>WSL2 のインストール</title><link>https://blog.ponkotools.com/posts/2022/01/15/wsl/</link><pubDate>Sat, 15 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/15/wsl/</guid><description>&lt;p&gt;WSL2 をインストールし、WSL2 上で Ubuntu を動かす方法です。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Windows 10 Pro OSビルド 19042.1466&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="wsl2-のインストール"&gt;&lt;a href="#wsl2-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;WSL2 のインストール
&lt;/h2&gt;&lt;p&gt;公式ドキュメントは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.microsoft.com/ja-jp/windows/wsl/install" target="_blank" rel="noopener"
 &gt;https://docs.microsoft.com/ja-jp/windows/wsl/install&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.microsoft.com/ja-jp/windows/wsl/install-manual" target="_blank" rel="noopener"
 &gt;https://docs.microsoft.com/ja-jp/windows/wsl/install-manual&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="wsl-のインストール"&gt;&lt;a href="#wsl-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;WSL のインストール
&lt;/h3&gt;&lt;p&gt;PowerShell を起動し、以下のコマンドを入力します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; wsl --install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="wsl2-にアップデート"&gt;&lt;a href="#wsl2-%e3%81%ab%e3%82%a2%e3%83%83%e3%83%97%e3%83%87%e3%83%bc%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;WSL2 にアップデート
&lt;/h3&gt;&lt;p&gt;以下にアクセスし、wsl_update_x64.msiをダウンロードしてインストールします。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://aka.ms/wsl2kernel" target="_blank" rel="noopener"
 &gt;https://aka.ms/wsl2kernel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="wsl2-をデフォルトにする"&gt;&lt;a href="#wsl2-%e3%82%92%e3%83%87%e3%83%95%e3%82%a9%e3%83%ab%e3%83%88%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;WSL2 をデフォルトにする
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; wsl --set-default-version 2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="ubuntu-のインストール"&gt;&lt;a href="#ubuntu-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;Ubuntu のインストール
&lt;/h2&gt;&lt;p&gt;MS Store から Ubuntu で検索してインストールするだけです。&lt;/p&gt;
&lt;h3 id="wsl2-で動作しているか確認"&gt;&lt;a href="#wsl2-%e3%81%a7%e5%8b%95%e4%bd%9c%e3%81%97%e3%81%a6%e3%81%84%e3%82%8b%e3%81%8b%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;WSL2 で動作しているか確認
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; wsl --list --verbose
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; NAME STATE VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* Ubuntu Running 2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;*&lt;/code&gt; が付いているのがデフォルトのディストリビューションです。
VERSION が 2 になっているので、WSL2 で動作しています。&lt;/p&gt;
&lt;p&gt;デフォルトのディストリビューションを変更する場合は、以下のように変更します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; wsl --set-default Ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;WSL のバージョンが2でない場合、以下のようにして設定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; wsl --set-version Ubuntu 2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.microsoft.com/ja-jp/windows/wsl/install" target="_blank" rel="noopener"
 &gt;https://docs.microsoft.com/ja-jp/windows/wsl/install&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.microsoft.com/ja-jp/windows/wsl/install-manual" target="_blank" rel="noopener"
 &gt;https://docs.microsoft.com/ja-jp/windows/wsl/install-manual&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.4peace.co.jp/tech/569/" target="_blank" rel="noopener"
 &gt;https://www.4peace.co.jp/tech/569/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Docker コンテナの内容を変更して、既存のイメージに上書きする</title><link>https://blog.ponkotools.com/posts/2022/01/13/docker/</link><pubDate>Thu, 13 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/13/docker/</guid><description>&lt;p&gt;&lt;code&gt;docker commit&lt;/code&gt; を行う際に忘れがちなのでメモです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker commit コンテナ名 使用中のイメージ名:タグ
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;例&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker commit hoge piyo:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;hoge&lt;/code&gt; というコンテナを &lt;code&gt;piyo:latest&lt;/code&gt; というイメージで保存します。&lt;br&gt;
そのイメージが既に存在する場合は上書きされます。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/mats16/items/712575dc50513dfdf0a2" target="_blank" rel="noopener"
 &gt;https://qiita.com/mats16/items/712575dc50513dfdf0a2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>GPU を複数積んでいるマシンで、GPU を指定して Docker コンテナを動かす</title><link>https://blog.ponkotools.com/posts/2022/01/12/docker/</link><pubDate>Wed, 12 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/12/docker/</guid><description>&lt;p&gt;タイトルの通りです。&lt;code&gt;docker run&lt;/code&gt; での指定方法と、docker-compose での指定方法です。&lt;/p&gt;
&lt;h2 id="docker-run-での指定方法"&gt;&lt;a href="#docker-run-%e3%81%a7%e3%81%ae%e6%8c%87%e5%ae%9a%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;docker run での指定方法
&lt;/h2&gt;&lt;p&gt;以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://cocoinit23.com/docker-run-multi-gpu/" target="_blank" rel="noopener"
 &gt;https://cocoinit23.com/docker-run-multi-gpu/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;全ての GPU を指定する場合は &lt;code&gt;--gpus all&lt;/code&gt; を指定します。&lt;/p&gt;
&lt;p&gt;特定の GPU を指定する場合は &lt;code&gt;--gpus '&amp;quot;device=0&amp;quot;'&lt;/code&gt; のように指定します。&lt;/p&gt;
&lt;h2 id="docker-compose-での指定方法"&gt;&lt;a href="#docker-compose-%e3%81%a7%e3%81%ae%e6%8c%87%e5%ae%9a%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;docker-compose での指定方法
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;--gpus all&lt;/code&gt; に相当する書き方は以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;reservations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;gpu]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;--gpus '&amp;quot;device=0&amp;quot;'&lt;/code&gt; に相当する書き方は以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;reservations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;gpu]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;device_ids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;詳細は公式のドキュメントに書いてあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/compose/gpu-support/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/compose/gpu-support/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="docker-compose-のアップデート"&gt;&lt;a href="#docker-compose-%e3%81%ae%e3%82%a2%e3%83%83%e3%83%97%e3%83%87%e3%83%bc%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;docker-compose のアップデート
&lt;/h3&gt;&lt;p&gt;私の環境では docker-compose のバージョンは 1.25.0 でしたが、docker-compose で GPU を使えるようにするためには 1.28.0 以上でなければならないようなので、そのような場合にはアップデートが必要です。&lt;br&gt;
docker-compose のアップデート方法については以下を参考にしてください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2022/09/docker-compose.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2022/09/docker-compose.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://cocoinit23.com/docker-run-multi-gpu/" target="_blank" rel="noopener"
 &gt;https://cocoinit23.com/docker-run-multi-gpu/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/compose/gpu-support/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/compose/gpu-support/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] URL のエンコード・デコード</title><link>https://blog.ponkotools.com/posts/2022/01/07/python/</link><pubDate>Fri, 07 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/07/python/</guid><description>&lt;p&gt;URL に使用できない文字を使用する場合、URL エンコードを行う必要があります。&lt;/p&gt;
&lt;p&gt;例えば REST API の GET メソッドのクエリパラメーターで、日時を ISO8601 形式で渡す必要がある場合、&lt;code&gt;+&lt;/code&gt; や &lt;code&gt;:&lt;/code&gt; が含まれるので、URL エンコード・デコードが必要になります。&lt;br&gt;
エンコード・デコードには、&lt;code&gt;urllib.parse&lt;/code&gt; を使います。&lt;/p&gt;
&lt;h2 id="エンコード"&gt;&lt;a href="#%e3%82%a8%e3%83%b3%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;エンコード
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from datetime import datetime
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from urllib import parse
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dt = datetime.now()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;encoded = parse.quote(dt.isoformat())
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(dt.isoformat()) # エンコード前
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(encoded) # エンコード後
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;出力結果&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-01-07T13:06:54.927884
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-01-07T13%3A06%3A54.927884
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="デコード"&gt;&lt;a href="#%e3%83%87%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;デコード
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;decoded = parse.unquote(&amp;#39;2022-01-07T13%3A06%3A54.927884&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(decoded)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;出力結果&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2022-01-07T13:06:54.927884
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>[Python] 2つの日付を比較し、日付が変わったことを検知する</title><link>https://blog.ponkotools.com/posts/2022/01/06/python/</link><pubDate>Thu, 06 Jan 2022 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2022/01/06/python/</guid><description>&lt;p&gt;日次処理を行う場合など、日付が変わったことを検知したい場合は以下のようにして検知できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;d0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2008&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2008&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;d0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# do something&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;要点は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;date&lt;/code&gt; や &lt;code&gt;datetime&lt;/code&gt; の演算結果は &lt;code&gt;timedelta&lt;/code&gt; 型&lt;/li&gt;
&lt;li&gt;&lt;code&gt;datetime&lt;/code&gt; 型の場合は &lt;code&gt;date()&lt;/code&gt; を使用することで時刻を無視できる（日付のみを取得できる）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;timedelta&lt;/code&gt; 型の &lt;code&gt;days&lt;/code&gt; で総日数が取得できる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/151199/how-to-calculate-number-of-days-between-two-given-dates" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/151199/how-to-calculate-number-of-days-between-two-given-dates&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Telegraf で Docker の情報を 取得して Grafana で可視化する</title><link>https://blog.ponkotools.com/posts/2021/12/27/telegraf-grafana/</link><pubDate>Mon, 27 Dec 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/12/27/telegraf-grafana/</guid><description>&lt;p&gt;サーバーリソースの可視化は以前やったので、今度は Docker の情報を可視化してみました。&lt;/p&gt;
&lt;p&gt;Grafana のダッシュボードは以下を使いました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/grafana/dashboards/10585" target="_blank" rel="noopener"
 &gt;https://grafana.com/grafana/dashboards/10585&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これに書いてあることをやっただけですが・・・。&lt;/p&gt;
&lt;h2 id="telegrafconf-の設定"&gt;&lt;a href="#telegrafconf-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;telegraf.conf の設定
&lt;/h2&gt;&lt;p&gt;以下を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;unix:///var/run/docker.sock&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gather_services&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;container_name_include&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;container_name_exclude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;5s&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;docker_label_include&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;docker_label_exclude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;perdevice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="docker-composeyaml-の設定"&gt;&lt;a href="#docker-composeyaml-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;docker-compose.yaml の設定
&lt;/h2&gt;&lt;p&gt;Telegraf の volume に &lt;code&gt;/var/run/docker.sock&lt;/code&gt; を追加します。&lt;br&gt;
また、&lt;code&gt;/var/run/docker.sock&lt;/code&gt; にアクセスするためには Telegraf の実行ユーザーを Docker と同じにする必要があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.influxdata.com/blog/docker-run-telegraf-as-non-root/" target="_blank" rel="noopener"
 &gt;https://www.influxdata.com/blog/docker-run-telegraf-as-non-root/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;133&lt;/span&gt; &lt;span class="c1"&gt;# UID:GID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;さらに、情報を習得したい全サービスに以下を追加してグループ化します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;labels:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &amp;#34;docker.group=&amp;lt;some_name&amp;gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ラベルの名前は何でもいいようです。&lt;br&gt;
ラベルを設定しなかったサービスの情報は取得されませんでした。&lt;/p&gt;
&lt;h2 id="grafana-の設定"&gt;&lt;a href="#grafana-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Grafana の設定
&lt;/h2&gt;&lt;p&gt;以下から JSON ファイルをダウンロードし、Grafana でインポートします。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/grafana/dashboards/10585" target="_blank" rel="noopener"
 &gt;https://grafana.com/grafana/dashboards/10585&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上で以下のようなダッシュボードが表示されます。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="515px" data-flex-grow="214" height="933" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2021/12/27/telegraf-grafana/01.webp" srcset="https://blog.ponkotools.com/posts/2021/12/27/telegraf-grafana/01_hu_3ea807a2ee27bfa9.webp 800w, https://blog.ponkotools.com/posts/2021/12/27/telegraf-grafana/01_hu_4a0caec175c09e8c.webp 1600w, https://blog.ponkotools.com/posts/2021/12/27/telegraf-grafana/01.webp 2005w" width="2005"&gt;&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/grafana/dashboards/10585" target="_blank" rel="noopener"
 &gt;https://grafana.com/grafana/dashboards/10585&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.influxdata.com/blog/docker-run-telegraf-as-non-root/" target="_blank" rel="noopener"
 &gt;https://www.influxdata.com/blog/docker-run-telegraf-as-non-root/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Telegraf で GPU の情報を取得し、Grafana で可視化する</title><link>https://blog.ponkotools.com/posts/2021/12/26/telegraf-grafana/</link><pubDate>Sun, 26 Dec 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/12/26/telegraf-grafana/</guid><description>&lt;p&gt;Telegraf, InfluxDB, Grafana を使って GPU の情報を閲覧できるようにしました。&lt;/p&gt;
&lt;p&gt;以前、Telegraf, InfluxDB, Grafana を使ってサーバーリソースの情報を閲覧できるようにしました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/12/telegraf-influxdb-garafana.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2021/12/telegraf-influxdb-garafana.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これを前提としたうえで、今回 GPU の情報も見れるようにしました。&lt;/p&gt;
&lt;p&gt;試したグラフィックボードは NVIDIA GeForce RTX 3080 です。&lt;br&gt;
グラフィックドライバーのインストールなどは完了している前提です。&lt;/p&gt;
&lt;h2 id="概要"&gt;&lt;a href="#%e6%a6%82%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;概要
&lt;/h2&gt;&lt;p&gt;Telegraf の nvidia_smi プラグインを使えば GPU の情報を取得できるようです。&lt;br&gt;
nvidia_smi のプラグインについては以下に説明があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/influxdata/telegraf/blob/master/plugins/inputs/nvidia_smi/README.md" target="_blank" rel="noopener"
 &gt;https://github.com/influxdata/telegraf/blob/master/plugins/inputs/nvidia_smi/README.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上記の記事に書いてありますが、Docker で動作させている Telegraf で GPU の情報を取得するには、以下の２つの方法があるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nvidia/cuda&lt;/code&gt; の Docker イメージをベースに Telegraf をインストールしたカスタムイメージを作成する&lt;/li&gt;
&lt;li&gt;Volume のマウントバインディングを使用して nvidia-smi のバイナリを Docker コンテナに注入する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回は後者でいきます。&lt;/p&gt;
&lt;h2 id="telegraf-の設定"&gt;&lt;a href="#telegraf-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Telegraf の設定
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;telegraf.conf&lt;/code&gt; に以下を追加しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[[inputs.nvidia_smi]]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; #bin_path = &amp;#34;/usr/bin/nvidia-smi&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;inputs.nvidia_smi&lt;/code&gt; を追加するだけでプラグインが有効になるようです。&lt;br&gt;
&lt;code&gt;bin_path&lt;/code&gt; は &lt;code&gt;nvidia-smi&lt;/code&gt; のある場所です。&lt;br&gt;
以下のコマンドで調べられます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ which nvidia-smi
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/usr/bin/nvidia-smi
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Linux では通常 &lt;code&gt;/usr/bin/nvidia-smi&lt;/code&gt; にあるそうで、その場合は指定しなくてもよいそうです。&lt;/p&gt;
&lt;h2 id="docker-compose-の設定"&gt;&lt;a href="#docker-compose-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;docker-compose の設定
&lt;/h2&gt;&lt;p&gt;Telegraf を動作させている Docker コンテナから nvidia-smi と GPU にアクセスできるように設定します。&lt;br&gt;
例えば、以下のような感じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;version: &amp;#39;3.5&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;services:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; telegraf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; container_name: telegraf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: telegraf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; environment:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - NVIDIA_VISIBLE_DEVICES=all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - NVIDIA_DRIVER_CAPABILITIES=all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; deploy:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resources:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; reservations:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; devices:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - capabilities: [gpu]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - /usr/bin/nvidia-smi:/usr/bin/nvidia-smi:ro
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ホストの &lt;code&gt;/usr/bin/nvidia-smi&lt;/code&gt; をコンテナにマウントします。&lt;br&gt;
Docker コンテナでの GPU の使用については以下の記事にも書いているので、参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/11/docker-compose-gpu.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2021/11/docker-compose-gpu.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="grafana-の設定"&gt;&lt;a href="#grafana-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Grafana の設定
&lt;/h2&gt;&lt;p&gt;Docker コンテナを起動したら、Grafana で以下のダッシュボードのテンプレートをインストールします。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/grafana/dashboards/12225" target="_blank" rel="noopener"
 &gt;https://grafana.com/grafana/dashboards/12225&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これで閲覧できるようになると思ったのですが、&lt;code&gt;Hostname&lt;/code&gt; に &lt;code&gt;None&lt;/code&gt; しか表示されず、グラフに何も表示されない状態でした。&lt;br&gt;
どうもこのテンプレートが Windows を前提としているようですので、ダッシュボードの設定をちょっと修正しました。&lt;/p&gt;
&lt;p&gt;ダッシュボードの設定画面を開き Variables を選択します。&lt;br&gt;
&lt;code&gt;hostname&lt;/code&gt; の定義を以下のように変更します。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;変更前&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SHOW TAG VALUES FROM &amp;#34;win_system&amp;#34; WITH KEY = &amp;#34;host&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;変更後&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SHOW TAG VALUES FROM system WITH KEY=host
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで以下のようにグラフが表示されるようになりました。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="394px" data-flex-grow="164" height="427" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2021/12/26/telegraf-grafana/01.webp" width="701"&gt;&lt;/p&gt;
&lt;p&gt;他に &lt;code&gt;CPU Usage&lt;/code&gt; と &lt;code&gt;Memory Free&lt;/code&gt; のメーター表示も Windows 前提となっているようなので、必要なら修正してください。&lt;br&gt;
私は CPU やメモリなどは他のダッシュボードで閲覧しており、ここでは GPU の情報だけで十分だったので、そこまで修正しませんでした。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/influxdata/telegraf/blob/master/plugins/inputs/nvidia_smi/README.md" target="_blank" rel="noopener"
 &gt;https://github.com/influxdata/telegraf/blob/master/plugins/inputs/nvidia_smi/README.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://cristianpb.github.io/blog/grafana-dashboard" target="_blank" rel="noopener"
 &gt;https://cristianpb.github.io/blog/grafana-dashboard&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] Docker コンテナ内のアプリのログをホストの Syslog に追加する</title><link>https://blog.ponkotools.com/posts/2021/12/24/docker-syslog/</link><pubDate>Fri, 24 Dec 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/12/24/docker-syslog/</guid><description>&lt;p&gt;docker コンテナ内で動作している python アプリのログをホストの syslog に追加します。&lt;/p&gt;
&lt;p&gt;Ubuntu 20.04 で作業しましたが、rsyslog は最初からインストールされていました。&lt;/p&gt;
&lt;h2 id="概要"&gt;&lt;a href="#%e6%a6%82%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;概要
&lt;/h2&gt;&lt;p&gt;Python 標準の logging モジュールに syslog 出力用のハンドラ &lt;code&gt;SysLogHandler&lt;/code&gt; があるので、アプリ側ではそれを指定するだけで OK です。&lt;/p&gt;
&lt;p&gt;Syslog はホストに対して UDP でログを送信して追加します。&lt;br&gt;
理由は以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;docker コンテナ内でアプリを動かしているので、今後コンテナが増えたときコンテナごとに rsyslog を設定してやるのが面倒そう&lt;/li&gt;
&lt;li&gt;各コンテナのログを一箇所に集約したい&lt;/li&gt;
&lt;li&gt;syslog の記録には TCP or UDP のポート 514 が使用されるらしいが、&lt;code&gt;SysLogHandler&lt;/code&gt; では UDP しか対応していないよう&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="rsyslog-の設定変更"&gt;&lt;a href="#rsyslog-%e3%81%ae%e8%a8%ad%e5%ae%9a%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;rsyslog の設定変更
&lt;/h2&gt;&lt;p&gt;UDP のポート514 でログを待ち受けるように設定を変更します。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/etc/rsyslog.conf&lt;/code&gt; を編集します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo gedit /etc/rsyslog.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下の２行のコメントを外します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;load&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;imudp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;imudp&amp;#34;&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;514&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;変更後は再起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart rsyslog
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="アプリ側の実装"&gt;&lt;a href="#%e3%82%a2%e3%83%97%e3%83%aa%e5%81%b4%e3%81%ae%e5%ae%9f%e8%a3%85" class="header-anchor"&gt;&lt;/a&gt;アプリ側の実装
&lt;/h2&gt;&lt;p&gt;ログに関する設定を &lt;code&gt;logging.yaml&lt;/code&gt; に切り出しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/12/python_21.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2021/12/python_21.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;その前提のうえで、以下のように指定するだけでログが UDP で送信されるようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; level: DEBUG
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; handlers: [syslog]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;handlers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; syslog:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; class: logging.handlers.SysLogHandler
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; formatter: syslog_format
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; address: [&amp;#39;host.docker.internal&amp;#39;, 514]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; #address: &amp;#39;/dev/log&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; level: INFO
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;formatters:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; syslog_format:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; format: &amp;#39;appname: %(module)s %(message)s&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;IPアドレスについては、docker コンテナからホストのIPアドレスを参照する必要があるので &lt;code&gt;host.docker.internal&lt;/code&gt; を指定します。&lt;br&gt;
（localhost はコンテナ自身を指すので使えない)&lt;br&gt;
ちなみに &lt;code&gt;host.docker.internal&lt;/code&gt; はもともと Windows と Mac でしか使えませんでしたが、最近 Linux でも使えるようになったそうです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/skobaken/items/03a8b9d0e443745862ac" target="_blank" rel="noopener"
 &gt;https://qiita.com/skobaken/items/03a8b9d0e443745862ac&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これ使えなかったら直接IPアドレスを指定しないといけなくなり、ホストのIPアドレスが変わるたびに修正しないといけなくてマジ困ります。
ってかこれを知るまでずっと困ってました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/Esfahan/items/7888914dca0e8d23eac3" target="_blank" rel="noopener"
 &gt;https://qiita.com/Esfahan/items/7888914dca0e8d23eac3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.alexgittings.com/capturing-syslog-with-the-tig-stack/" target="_blank" rel="noopener"
 &gt;https://blog.alexgittings.com/capturing-syslog-with-the-tig-stack/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] Flask (Werkzeug)のロギングの設定</title><link>https://blog.ponkotools.com/posts/2021/12/23/flask/</link><pubDate>Thu, 23 Dec 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/12/23/flask/</guid><description>&lt;p&gt;Flask (というか Werkzeug？) が HTTP リクエストを受信するたびにログをレベル &lt;code&gt;INFO&lt;/code&gt; で出力するので、&lt;code&gt;ERROR&lt;/code&gt; 以上のログのみ出力するように設定を変更しました。&lt;/p&gt;
&lt;h2 id="前提"&gt;&lt;a href="#%e5%89%8d%e6%8f%90" class="header-anchor"&gt;&lt;/a&gt;前提
&lt;/h2&gt;&lt;p&gt;ログに関する設定は yaml ファイルに切り出しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/12/python_21.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2021/12/python_21.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="flask-werkzeug-のロギングの設定"&gt;&lt;a href="#flask-werkzeug-%e3%81%ae%e3%83%ad%e3%82%ae%e3%83%b3%e3%82%b0%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Flask (Werkzeug) のロギングの設定
&lt;/h2&gt;&lt;p&gt;Flask は Werkzeug という WSGI サーバーに依存しており、こちらがいろいろログを出力しているようなので、&lt;code&gt;werkzeug&lt;/code&gt; のロギングの設定を追加します。&lt;br&gt;
例えば、以下のように指定すれば &lt;code&gt;ERROR&lt;/code&gt; レベル以上のログのみ出力されるようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;loggers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; werkzeug:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; level: ERROR
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>rsyslog から Telegraf への送信に時々失敗する</title><link>https://blog.ponkotools.com/posts/2021/12/22/rsyslog-telegraf/</link><pubDate>Wed, 22 Dec 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/12/22/rsyslog-telegraf/</guid><description>&lt;p&gt;rsyslog から Telegraf にログを TCP で転送するように設定してみましたが、Grafana で閲覧していると表示されないログがあり、送信に失敗しているようでした。&lt;/p&gt;
&lt;p&gt;ググてみると以下のページを見つけました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gist.github.com/froop/e3a1e7d14a8143f9951b85afff6b5469#file-rsyslog-bug4227-md" target="_blank" rel="noopener"
 &gt;https://gist.github.com/froop/e3a1e7d14a8143f9951b85afff6b5469#file-rsyslog-bug4227-md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;どうやら rsyslog の不具合のようで、バージョン 8.2010.0 で修正されているようです。&lt;br&gt;
rsyslog のバージョンは以下で確認できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ rsyslogd -v
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;私の環境 (Ubuntu 20.04) の rsyslog のバージョンは 8.2001.0 でした。
なので、rsyslog をアップデートします。
アップデート方法は以下に書いてありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.rsyslog.com/ubuntu-repository/" target="_blank" rel="noopener"
 &gt;https://www.rsyslog.com/ubuntu-repository/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo add-apt-repository ppa:adiscon/v8-stable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt-get install rsyslog
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;現在の &lt;code&gt;/etc/rsyslog.conf&lt;/code&gt; を最新のに差し替えるか残すかを聞かれますが、最新のに差し替えた後で再設定を行いました。
再設定後は rsyslog を再起動します。
尚、アップデート後のバージョンは 8.2021.0 でした。
アップデート後は、ざっと見た感じきちんと転送されているように見えます。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gist.github.com/froop/e3a1e7d14a8143f9951b85afff6b5469#file-rsyslog-bug4227-md" target="_blank" rel="noopener"
 &gt;https://gist.github.com/froop/e3a1e7d14a8143f9951b85afff6b5469#file-rsyslog-bug4227-md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.rsyslog.com/ubuntu-repository/" target="_blank" rel="noopener"
 &gt;https://www.rsyslog.com/ubuntu-repository/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] コンソールに出力するログに色を付ける</title><link>https://blog.ponkotools.com/posts/2021/12/21/python/</link><pubDate>Tue, 21 Dec 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/12/21/python/</guid><description>&lt;p&gt;ググればやり方はいろいろ見つかり、いろいろ試してみましたが、&lt;code&gt;rich&lt;/code&gt; を使うのが一番簡単かつ見栄えがいいかもしれません。&lt;/p&gt;
&lt;h2 id="前提"&gt;&lt;a href="#%e5%89%8d%e6%8f%90" class="header-anchor"&gt;&lt;/a&gt;前提
&lt;/h2&gt;&lt;p&gt;ログに関する設定は yaml ファイルに切り出しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/12/python_21.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2021/12/python_21.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="coloredlogs-を使う方法"&gt;&lt;a href="#coloredlogs-%e3%82%92%e4%bd%bf%e3%81%86%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;coloredlogs を使う方法
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install coloredlogs
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./logging.yaml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logconfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;safe_load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dictConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logconfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;coloredlogs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;DEBUG&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 追加&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;簡単にカラフルに出来ましたが、 &lt;code&gt;logging.yaml&lt;/code&gt; の設定が上書きされてしまいました。&lt;br&gt;
他にやり方があるのかもしれません。&lt;/p&gt;
&lt;h2 id="colorlog-を使う方法"&gt;&lt;a href="#colorlog-%e3%82%92%e4%bd%bf%e3%81%86%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;colorlog を使う方法
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install colorlog
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;logging.yaml&lt;/code&gt; で、&lt;code&gt;colorlog&lt;/code&gt; を使うように指定し、&lt;code&gt;{log_color}&lt;/code&gt; でレベルに合わせた色分けをしてくれます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;DEBUG&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;console]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;console&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;logging.StreamHandler&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ext://sys.stderr&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;myformatter&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;formatters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;myformatter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#39;()&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;colorlog.ColoredFormatter&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{log_color}{asctime} [{levelname:.4}] {name}: {message}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="各レベルの色を自分で定義"&gt;&lt;a href="#%e5%90%84%e3%83%ac%e3%83%99%e3%83%ab%e3%81%ae%e8%89%b2%e3%82%92%e8%87%aa%e5%88%86%e3%81%a7%e5%ae%9a%e7%be%a9" class="header-anchor"&gt;&lt;/a&gt;各レベルの色を自分で定義
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;DEBUG&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;console]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;console&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;logging.StreamHandler&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ext://sys.stderr&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;myformatter&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;formatters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;myformatter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#39;()&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;colorlog.ColoredFormatter&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{log_color}{asctime} [{levelname:.4}] {name}: {message}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;log_colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;bold_black&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;white&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;WARNING&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;yellow&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;red&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;CRITICAL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;bold_red&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="一つのログ内で色分けしたい場合"&gt;&lt;a href="#%e4%b8%80%e3%81%a4%e3%81%ae%e3%83%ad%e3%82%b0%e5%86%85%e3%81%a7%e8%89%b2%e5%88%86%e3%81%91%e3%81%97%e3%81%9f%e3%81%84%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;一つのログ内で色分けしたい場合
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;format&lt;/code&gt; で以下のように記述すれば OK です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{cyan}{asctime} {blue}{name} L{lineno} {bold_black}{levelname}{reset} {log_color}{message}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="rich-を使う方法"&gt;&lt;a href="#rich-%e3%82%92%e4%bd%bf%e3%81%86%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;rich を使う方法
&lt;/h2&gt;&lt;p&gt;コンソールへの出力をリッチにしてくれる &lt;code&gt;Rich&lt;/code&gt; というライブラリの &lt;code&gt;RichHandler&lt;/code&gt; を使ってログを出力する方法です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://note.com/navitime_tech/n/n6d8cd7327466c" target="_blank" rel="noopener"
 &gt;https://note.com/navitime_tech/n/n6d8cd7327466c&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install rich
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;rich]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;rich&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;rich.logging.RichHandler&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;rich_tracebacks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これだけで簡単にカラフルなログを出力してくれます。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/XPT60/items/65c09f8c7e18ef78a58d" target="_blank" rel="noopener"
 &gt;https://qiita.com/XPT60/items/65c09f8c7e18ef78a58d&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://connvoi.com/tech/2020/12/29/python-logging-config/" target="_blank" rel="noopener"
 &gt;https://connvoi.com/tech/2020/12/29/python-logging-config/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/amedama/items/b856b2f30c2f38665701" target="_blank" rel="noopener"
 &gt;https://qiita.com/amedama/items/b856b2f30c2f38665701&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/shinsa82/items/a0778fbd127012c93577" target="_blank" rel="noopener"
 &gt;https://qiita.com/shinsa82/items/a0778fbd127012c93577&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] ロギングの個人的ベストプラクティス</title><link>https://blog.ponkotools.com/posts/2021/12/20/python/</link><pubDate>Mon, 20 Dec 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/12/20/python/</guid><description>&lt;p&gt;まぁベストかどうかはわかりませんが、現状の私にとっての最適解です。&lt;/p&gt;
&lt;p&gt;Python 標準の logging モジュールを使用しますが、logging を直接使うのではなく、&lt;code&gt;getLogger&lt;/code&gt; でロガーを取得して使用します。&lt;br&gt;
これについては以下の記事にわかりやすく書いてありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/amedama/items/b856b2f30c2f38665701" target="_blank" rel="noopener"
 &gt;https://qiita.com/amedama/items/b856b2f30c2f38665701&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;このように抽象化しておけば、ロガーハンドラを指定・変更するだけで、ファイルに出力したり、syslog に出力したり、どっかに送信したりと後から簡単に出力先を変更できます。&lt;/p&gt;
&lt;h2 id="ロギングの設定をファイルに切り出す"&gt;&lt;a href="#%e3%83%ad%e3%82%ae%e3%83%b3%e3%82%b0%e3%81%ae%e8%a8%ad%e5%ae%9a%e3%82%92%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ab%e5%88%87%e3%82%8a%e5%87%ba%e3%81%99" class="header-anchor"&gt;&lt;/a&gt;ロギングの設定をファイルに切り出す
&lt;/h2&gt;&lt;p&gt;ログに関する設定は &lt;code&gt;logging.yaml&lt;/code&gt; というファイルに切り出すことにしました。&lt;br&gt;
これについては以下の記事にわかりやすく書いてありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/shinsa82/items/a0778fbd127012c93577" target="_blank" rel="noopener"
 &gt;https://qiita.com/shinsa82/items/a0778fbd127012c93577&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例えばこんな感じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt; &lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getLogger&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./logging.yaml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logconfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;safe_load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dictConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logconfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;critical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is critical&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is error&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is warning&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is info&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is debug&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;hoge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;except&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is exception&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;DEBUG&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;console]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;console&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;logging.StreamHandler&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ext://sys.stderr&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;myformatter&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;formatters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;myformatter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;%(asctime) [%(levelname:.4)s] %(name)s: %(message)s&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こうしておけば、環境に応じて設定を丸ごと差し替えたりも簡単にできます。&lt;br&gt;
フォーマッタで使える変数については以下を参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.python.org/3/library/logging.html#logrecord-attributes" target="_blank" rel="noopener"
 &gt;https://docs.python.org/3/library/logging.html#logrecord-attributes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="設定いろいろ"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a%e3%81%84%e3%82%8d%e3%81%84%e3%82%8d" class="header-anchor"&gt;&lt;/a&gt;設定いろいろ
&lt;/h2&gt;&lt;p&gt;ここらへんは環境や好みに応じて様々だと思うので、あくまでサンプルとして。&lt;br&gt;
適宜追加していきます。&lt;/p&gt;
&lt;h3 id="コンソール出力をカラフルにして見やすくする"&gt;&lt;a href="#%e3%82%b3%e3%83%b3%e3%82%bd%e3%83%bc%e3%83%ab%e5%87%ba%e5%8a%9b%e3%82%92%e3%82%ab%e3%83%a9%e3%83%95%e3%83%ab%e3%81%ab%e3%81%97%e3%81%a6%e8%a6%8b%e3%82%84%e3%81%99%e3%81%8f%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;コンソール出力をカラフルにして見やすくする
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;rich&lt;/code&gt; を使うのが簡単かつわかりやすかったです。&lt;br&gt;
例えば以下のような感じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;root:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; level: DEBUG
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; handlers: [rich]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;handlers:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; rich:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; class: rich.logging.RichHandler
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; rich_tracebacks: True
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下の記事も参考にしてください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/12/python_5.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2021/12/python_5.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="syslog-に出力する"&gt;&lt;a href="#syslog-%e3%81%ab%e5%87%ba%e5%8a%9b%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;syslog に出力する
&lt;/h3&gt;&lt;p&gt;logging モジュールに &lt;code&gt;SyslogHandler&lt;/code&gt; があるので、基本的にこれを指定するだけで OK です。&lt;br&gt;
詳細は別記事にまとめているので、以下を参考にしてください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/12/python-syslog.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2021/12/python-syslog.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="flask-の出力設定"&gt;&lt;a href="#flask-%e3%81%ae%e5%87%ba%e5%8a%9b%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;flask の出力設定
&lt;/h3&gt;&lt;p&gt;Flask が HTTP リクエストを受信するたびにログをレベル INFO で出力するので、ERROR 以上のログのみ出力するように設定変更する方法を以下の記事に書いています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/12/python-flask.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2021/12/python-flask.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/amedama/items/b856b2f30c2f38665701" target="_blank" rel="noopener"
 &gt;https://qiita.com/amedama/items/b856b2f30c2f38665701&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/shinsa82/items/a0778fbd127012c93577" target="_blank" rel="noopener"
 &gt;https://qiita.com/shinsa82/items/a0778fbd127012c93577&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.python.org/3/library/logging.html#logrecord-attributes" target="_blank" rel="noopener"
 &gt;https://docs.python.org/3/library/logging.html#logrecord-attributes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Syslog を Telegraf に送り、Grafana で閲覧できるようにする</title><link>https://blog.ponkotools.com/posts/2021/12/20/syslog-telegraf-grafana/</link><pubDate>Mon, 20 Dec 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/12/20/syslog-telegraf-grafana/</guid><description>&lt;p&gt;以下に Syslog 用のテンプレートと解説があるので簡単にできるかと思ったんですが、結構苦労しました・・・。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/grafana/dashboards/12433" target="_blank" rel="noopener"
 &gt;https://grafana.com/grafana/dashboards/12433&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="概要"&gt;&lt;a href="#%e6%a6%82%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;概要
&lt;/h2&gt;&lt;p&gt;ホストの Syslog から Telegraf にログを送り、Telegraf が InfluxDB に保存し、Grafana が InfluxDB から読み込んで可視化します。&lt;/p&gt;
&lt;p&gt;Telegraf、InfluxDB、Grafana は全て docker-compose で動かしています。&lt;br&gt;
これについては以下の記事で書いているので省略します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/12/telegraf-influxdb-garafana.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2021/12/telegraf-influxdb-garafana.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上記記事からの変更点を以下に記述します。&lt;/p&gt;
&lt;h2 id="rsyslog-の設定"&gt;&lt;a href="#rsyslog-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;rsyslog の設定
&lt;/h2&gt;&lt;p&gt;まずは Syslog から Telegraf にログを送信するように設定します。&lt;br&gt;
&lt;code&gt;/etc/rsyslog.conf&lt;/code&gt; を編集します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo gedit /etc/rsyslog.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下の設定を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;WorkDirectory&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;spool&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rsyslog&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;ActionQueueType&lt;/span&gt; &lt;span class="n"&gt;LinkedList&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;ActionQueueFileName&lt;/span&gt; &lt;span class="n"&gt;srvrfwd&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;ActionResumeRetryCount&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;ActionQueueSaveOnShutdown&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;ModLoad&lt;/span&gt; &lt;span class="n"&gt;imudp&lt;/span&gt; &lt;span class="c1"&gt;#loads the udp module &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;UDPServerAddress&lt;/span&gt; &lt;span class="n"&gt;localhost&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;UDPServerRun&lt;/span&gt; &lt;span class="mi"&gt;514&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;*.*&lt;/span&gt; &lt;span class="err"&gt;@@&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;6514&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;RSYSLOG_SyslogProtocol23Format&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;rsyslog を再起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo systemctl restart rsyslog
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="telegraf-の設定"&gt;&lt;a href="#telegraf-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Telegraf の設定
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;telegraf.conf&lt;/code&gt; に以下の設定を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[[inputs.syslog]]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; server = &amp;#34;tcp://0.0.0.0:6514&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Syslog から TCP ポート 6514 で受信するように設定していますが、docker で動かしているので &lt;code&gt;localhost&lt;/code&gt; を指定すると上手く動作しません。&lt;br&gt;
とりあえず &lt;code&gt;0.0.0.0&lt;/code&gt; を指定しましたが、もしかしたら &lt;code&gt;host.docker.internal&lt;/code&gt; とかでもいけるのかもしれません（未確認）。&lt;/p&gt;
&lt;h2 id="docker-composeyaml-の変更"&gt;&lt;a href="#docker-composeyaml-%e3%81%ae%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;docker-compose.yaml の変更
&lt;/h2&gt;&lt;p&gt;ポート 6514 を使用できるようにします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;services:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; telegraf:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; container_name: telegraf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: telegraf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ports:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 6514:6514
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;docker コンテナを再起動します。&lt;/p&gt;
&lt;h2 id="grafana-の設定"&gt;&lt;a href="#grafana-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Grafana の設定
&lt;/h2&gt;&lt;p&gt;以下のページからダッシュボードの JSON ファイルをダウンロードしてインポートするだけです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/grafana/dashboards/12433" target="_blank" rel="noopener"
 &gt;https://grafana.com/grafana/dashboards/12433&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これで以下のようなダッシュボードが完成します。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="338px" data-flex-grow="140" height="320" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2021/12/20/syslog-telegraf-grafana/01.webp" width="451"&gt;&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.htkyama.org/rsyslog_grafana" target="_blank" rel="noopener"
 &gt;https://blog.htkyama.org/rsyslog_grafana&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/grafana/dashboards/12433" target="_blank" rel="noopener"
 &gt;https://grafana.com/grafana/dashboards/12433&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/haccht/items/82e8694c57202135ae5e" target="_blank" rel="noopener"
 &gt;https://qiita.com/haccht/items/82e8694c57202135ae5e&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Telegraf + InfluxDB + Garafana でサーバーリソースを可視化する</title><link>https://blog.ponkotools.com/posts/2021/12/18/telegraf-influxdb-grafana/</link><pubDate>Sat, 18 Dec 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/12/18/telegraf-influxdb-grafana/</guid><description>&lt;p&gt;CPUやメモリなどのリソースを収集して閲覧したいなと思い、ググってみるとこの組み合わせが良さそうでした。&lt;br&gt;
Telegraf でデータを取得して InfluxDB に書き込み、Grafana で InfluxDB のデータを読み込んで可視化します。&lt;/p&gt;
&lt;p&gt;個人的に InfluxDB と Grafana は使ったことありますが、Telegraf は今回初めて使いました。&lt;/p&gt;
&lt;p&gt;尚、この３つの頭文字を取って TIG Stack と呼んでいるページもいくつか見かけました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;Docker 20.10.7&lt;/li&gt;
&lt;li&gt;Telegraf 1.20.4&lt;/li&gt;
&lt;li&gt;InfluxDB 1.8.6&lt;/li&gt;
&lt;li&gt;Grafana 7.5.7&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Telegraf と Grafana は現時点の最新のバージョンですが、InfluxDB は 2.0 系ではなく 1.8.6 を使いました。&lt;br&gt;
InfluxDB 2.0 を使ったことがないのと、参考にした Telegraf の設定ファイルのサンプルが InfluxDB 2.0 ではないものばかりだったからです。&lt;/p&gt;
&lt;p&gt;また、Telegraf, InfluxDB, Grafana は全て Docker (docker-compose) を使って動かします。&lt;/p&gt;
&lt;h2 id="docker-composeyaml-のサンプル"&gt;&lt;a href="#docker-composeyaml-%e3%81%ae%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;docker-compose.yaml のサンプル
&lt;/h2&gt;&lt;p&gt;以下のような &lt;code&gt;docker-compose.yaml&lt;/code&gt; を作成しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;3.1&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;telegraf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;telegraf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;telegraf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;telegraf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;telegraf&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;telegraf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ro&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;influxdb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;influxdb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;common&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;influxdb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;influxdb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;influxdb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.8&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;8086&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8086&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;influxdb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;influxdb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;common&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;grafana&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grafana&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grafana&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;grafana&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;influxdb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;grafana&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;grafana&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;common&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;common&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;influxdb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;grafana&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;common&lt;/code&gt; というネットワークを共通で使っているので、あらかじめ &lt;code&gt;docker network create&lt;/code&gt; で作成しておく必要があります。&lt;/p&gt;
&lt;h2 id="telegraf-の設定"&gt;&lt;a href="#telegraf-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Telegraf の設定
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;telegraf.conf&lt;/code&gt; を作成します。&lt;/p&gt;
&lt;p&gt;以下のページにちょうど良いのがあるのでこれをそのまま使いました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/grafana/dashboards/928" target="_blank" rel="noopener"
 &gt;https://grafana.com/grafana/dashboards/928&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;後述しますが、Grafana のダッシュボードのテンプレートもこれを使いました。&lt;br&gt;
上記の設定をコピーしたら最低限以下の設定だけ変更します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;[agent]&lt;/code&gt; &amp;gt; &lt;code&gt;hostname&lt;/code&gt; にマシン名を設定
&lt;ul&gt;
&lt;li&gt;設定しないと自動で設定されますが、起動の度に変わるので設定しておいたほうがよいと思います。&lt;/li&gt;
&lt;li&gt;環境変数が使えるので、&lt;code&gt;hostname = &amp;quot;$HOSTNAME&amp;quot;&lt;/code&gt; のようにも書けます。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[[outputs.influxdb]]&lt;/code&gt; &amp;gt; &lt;code&gt;urls&lt;/code&gt; を InfluxDB の URL に変更
&lt;ul&gt;
&lt;li&gt;上記の &lt;code&gt;docker-compose.yaml&lt;/code&gt; の場合、URL は &lt;code&gt;http://influxdb.common:8086&lt;/code&gt; のようにコンテナ名とネットワーク名を使っても指定できます。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;他は必要に応じて設定します。&lt;/p&gt;
&lt;h2 id="起動"&gt;&lt;a href="#%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;起動
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-compose up
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;デーモン化したい場合は &lt;code&gt;-d&lt;/code&gt; を指定します。&lt;br&gt;
起動すると InfluxDB に Telegraf 用のデータベースを自動で作成してくれます。&lt;br&gt;
（データベース名は &lt;code&gt;telegraf.conf&lt;/code&gt; で設定できます。）&lt;/p&gt;
&lt;h2 id="grafana-の設定"&gt;&lt;a href="#grafana-%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;Grafana の設定
&lt;/h2&gt;&lt;p&gt;Grafana にアクセスし、ログインします。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;http://localhost:3000&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;初期 ID とパスワードはどちらも &lt;code&gt;admin&lt;/code&gt; です。&lt;/p&gt;
&lt;h3 id="db-の登録"&gt;&lt;a href="#db-%e3%81%ae%e7%99%bb%e9%8c%b2" class="header-anchor"&gt;&lt;/a&gt;DB の登録
&lt;/h3&gt;&lt;p&gt;Configuration &amp;gt; Data Sources &amp;gt; Add data source &amp;gt; InfluxDB を選択します。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;URL&lt;/code&gt; と &lt;code&gt;Database&lt;/code&gt; の２つを設定します。&lt;br&gt;
今回の例では以下のように設定します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;URL&lt;/code&gt; に &lt;code&gt;http://influxdb.common:8086&lt;/code&gt; を設定&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Database&lt;/code&gt; に &lt;code&gt;telegraf_metrics&lt;/code&gt; を設定&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ダッシュボードの作成"&gt;&lt;a href="#%e3%83%80%e3%83%83%e3%82%b7%e3%83%a5%e3%83%9c%e3%83%bc%e3%83%89%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;ダッシュボードの作成
&lt;/h3&gt;&lt;p&gt;Telegraf 用のテンプレートがあるので、それをインポートするのが楽です。&lt;br&gt;
テンプレートは以下のページで探せます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/grafana/dashboards/" target="_blank" rel="noopener"
 &gt;https://grafana.com/grafana/dashboards/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回は以下のテンプレートを使いました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/grafana/dashboards/928" target="_blank" rel="noopener"
 &gt;https://grafana.com/grafana/dashboards/928&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上記から JSON ファイルをダウンロードし、Grafana の左メニューの + ボタンからインポートします。&lt;br&gt;
インポートの際、データベースは &lt;code&gt;telegraf_metrics&lt;/code&gt; を選択します。&lt;/p&gt;
&lt;p&gt;ダッシュボードにアクセスすると以下のような画面が表示されます。&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="377px" data-flex-grow="157" height="1275" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://blog.ponkotools.com/posts/2021/12/18/telegraf-influxdb-grafana/01.webp" srcset="https://blog.ponkotools.com/posts/2021/12/18/telegraf-influxdb-grafana/01_hu_1c1df1dba5082846.webp 800w, https://blog.ponkotools.com/posts/2021/12/18/telegraf-influxdb-grafana/01_hu_a462fb49fe1c77e3.webp 1600w, https://blog.ponkotools.com/posts/2021/12/18/telegraf-influxdb-grafana/01.webp 2003w" width="2003"&gt;&lt;/p&gt;
&lt;p&gt;かっこいい画面が簡単に作成できました。&lt;/p&gt;
&lt;h2 id="リテンションポリシーの設定"&gt;&lt;a href="#%e3%83%aa%e3%83%86%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%b3%e3%83%9d%e3%83%aa%e3%82%b7%e3%83%bc%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;リテンションポリシーの設定
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;telegraf.conf&lt;/code&gt; の [[outputs.influxdb]] &amp;gt; retention_policy でリテンションポリシーを指定できますが、ここが未指定だとデフォルトの &lt;code&gt;autogen&lt;/code&gt; が使用され、データが無期限に保存されることになるので指定します。&lt;br&gt;
例えば、リテンションポリシー名に &lt;code&gt;hoge&lt;/code&gt; と指定します。&lt;/p&gt;
&lt;p&gt;この状態で動作させると、&lt;code&gt;hoge&lt;/code&gt; というリテンションポリシーが存在しないというエラーが出るので、InfluxDB のコンテナに入ってリテンションポリシーを作成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker exec -it influxdb bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コンテナに入ったら以下のコマンドでリテンションポリシーを作成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# influx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; CREATE RETENTION POLICY &amp;#34;リテンションポリシー名&amp;#34; ON &amp;#34;データベース名&amp;#34; DURATION &amp;#34;期間&amp;#34; REPLICATION 1 DEFAULT
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;例えば、今回は以下のように指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CREATE RETENTION POLICY &amp;#34;hoge&amp;#34; ON &amp;#34;telegraf_metrics&amp;#34; DURATION 1h REPLICATION 1 DEFAULT
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上記のコマンドではデータの保存期間を１時間に設定しています。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/sammrai/items/0c329ac7aa8b100b66a8" target="_blank" rel="noopener"
 &gt;https://qiita.com/sammrai/items/0c329ac7aa8b100b66a8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/influxdata/telegraf/blob/master/etc/telegraf.conf" target="_blank" rel="noopener"
 &gt;https://github.com/influxdata/telegraf/blob/master/etc/telegraf.conf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/grafana/dashboards/928" target="_blank" rel="noopener"
 &gt;https://grafana.com/grafana/dashboards/928&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.htkyama.org/telegraf_influxdb_grafana" target="_blank" rel="noopener"
 &gt;https://blog.htkyama.org/telegraf_influxdb_grafana&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>docker デーモンが勝手に再起動する原因の調査と対策</title><link>https://blog.ponkotools.com/posts/2021/12/17/docker/</link><pubDate>Fri, 17 Dec 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/12/17/docker/</guid><description>&lt;p&gt;docker コンテナをずっと動作させていたのですが、次の日の朝に止まっていたことがありました。&lt;br&gt;
その原因の調査と対策方法についてのメモです。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;Docker 20.10.7&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="原因の調査"&gt;&lt;a href="#%e5%8e%9f%e5%9b%a0%e3%81%ae%e8%aa%bf%e6%9f%bb" class="header-anchor"&gt;&lt;/a&gt;原因の調査
&lt;/h2&gt;&lt;p&gt;まずは docker のログを調べてみます。
syslog から docker に関するログを表示します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;dockerd&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;log&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;syslog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Dec&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="n"&gt;dockerd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1880&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2021-12-17T07:02:17.017091451+09:00&amp;#34;&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Processing signal &amp;#39;terminated&amp;#39;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;中略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Dec&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt; &lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="n"&gt;dockerd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1880&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2021-12-17T07:02:27.985252607+09:00&amp;#34;&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Daemon shutdown complete&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Dec&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt; &lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="n"&gt;systemd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Succeeded&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Dec&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt; &lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="n"&gt;dockerd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;327103&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2021-12-17T07:02:28.012481765+09:00&amp;#34;&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Starting up&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;中略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Dec&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt; &lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="n"&gt;dockerd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;327297&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2021-12-17T07:02:28.618499702+09:00&amp;#34;&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Daemon has completed initialization&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Dec&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt; &lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="n"&gt;dockerd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;327297&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2021-12-17T07:02:28.627472728+09:00&amp;#34;&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;API listen on /run/docker.sock&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;docker としては、終了指示を受けたから停止して、その後正しく再起動しているようです。&lt;/p&gt;
&lt;p&gt;じゃあ何で（誰が）終了したのかということで、今度はログ全部を表示して docker 再起動の少し前をログを見てみました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;log&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;syslog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;怪しいログとして以下がありました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Dec&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt; &lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="n"&gt;systemd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;Starting&lt;/span&gt; &lt;span class="n"&gt;Daily&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;download&lt;/span&gt; &lt;span class="n"&gt;activities&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;中略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Dec&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="n"&gt;systemd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;Stopping&lt;/span&gt; &lt;span class="n"&gt;Docker&lt;/span&gt; &lt;span class="n"&gt;Application&lt;/span&gt; &lt;span class="ne"&gt;Container&lt;/span&gt; &lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;日次処理が走った後に docker を再起動している？&lt;br&gt;
また、ググってみたら以下のページが見つかりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/65090971/docker-daemon-unexpectedly-exits" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/65090971/docker-daemon-unexpectedly-exits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;というわけで、ソフトウェアの自動アップデートが走った結果 docker が再起動したのが原因のようです。&lt;br&gt;
実際、ソフトウェアのアップデートの設定を確認したら、たしかに自動アップデートするようになっていました。&lt;br&gt;
自動アップデートを無効にしてもいいですが、とりあえずこれはこのままにしておきました。&lt;/p&gt;
&lt;h2 id="docker-コンテナの-restart-フラグ"&gt;&lt;a href="#docker-%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e3%81%ae-restart-%e3%83%95%e3%83%a9%e3%82%b0" class="header-anchor"&gt;&lt;/a&gt;docker コンテナの restart フラグ
&lt;/h2&gt;&lt;p&gt;今までも docker コンテナをサービス化するときには &lt;code&gt;restart&lt;/code&gt; フラグを設定していました。&lt;br&gt;
&lt;code&gt;restart&lt;/code&gt; については以下に記述があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://matsuand.github.io/docs.docker.jp.onthefly/config/containers/start-containers-automatically/#use-a-restart-policy" target="_blank" rel="noopener"
 &gt;https://matsuand.github.io/docs.docker.jp.onthefly/config/containers/start-containers-automatically/#use-a-restart-policy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回はエラーで Docker デーモンが再起動したわけではないので、今回のような場合でも Docker コンテナを再起動させるためには &lt;code&gt;unless-stopped&lt;/code&gt; ではなく &lt;code&gt;always&lt;/code&gt; を指定しないといけないっぽいですね。&lt;/p&gt;
&lt;p&gt;ちなみに、GUI アプリで &lt;code&gt;restart&lt;/code&gt; を &lt;code&gt;unless-stopped&lt;/code&gt; or &lt;code&gt;always&lt;/code&gt; に指定してサービス化した場合、 ×ボタンなどでアプリを終了してもすぐ再起動して GUI が立ち上がるようになるので、そこは注意が必要です。&lt;br&gt;
まぁ GUI アプリをサービス化なんてしませんね。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/65090971/docker-daemon-unexpectedly-exits" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/65090971/docker-daemon-unexpectedly-exits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://matsuand.github.io/docs.docker.jp.onthefly/config/containers/start-containers-automatically/#use-a-restart-policy" target="_blank" rel="noopener"
 &gt;https://matsuand.github.io/docs.docker.jp.onthefly/config/containers/start-containers-automatically/#use-a-restart-policy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] 指定したディレクトリ内の空ディレクトリを全て削除する</title><link>https://blog.ponkotools.com/posts/2021/12/14/python/</link><pubDate>Tue, 14 Dec 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/12/14/python/</guid><description>&lt;p&gt;空のディレクトリを削除する方法自体はググればたくさん見つかりますが、指定したディレクトリ内を再帰的に検索して空のディレクトリを削除する方法が見つからなかったので実装してみました。&lt;/p&gt;
&lt;p&gt;もっと他に良いやり方はあるかもしれせんが・・・。&lt;/p&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;/hoge&lt;/code&gt; 内の空ディレクトリを削除するサンプルコードです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;target_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/hoge&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dirs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;target_dir&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;/**/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recursive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; dirs exist&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;dir&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;removedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Removed dir: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cnt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;OSError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cnt&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Removed &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; dirs&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ディレクト一覧の取得は &lt;code&gt;glob&lt;/code&gt; で行います。&lt;br&gt;
再帰的に取得するため &lt;code&gt;recursive=True&lt;/code&gt; を指定します。&lt;/p&gt;
&lt;p&gt;ディレクトリの削除は &lt;code&gt;os.removedirs&lt;/code&gt; で行います。&lt;br&gt;
空のディレクトリを削除し、その結果親ディレクトリも空になればそちらも削除してくれます。&lt;br&gt;
ディレクトリが空でなかった場合は &lt;code&gt;OSError&lt;/code&gt; になります。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://note.nkmk.me/python-os-remove-rmdir-removedirs-shutil-rmtree/" target="_blank" rel="noopener"
 &gt;https://note.nkmk.me/python-os-remove-rmdir-removedirs-shutil-rmtree/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Docker のディスク使用量を調べる</title><link>https://blog.ponkotools.com/posts/2021/12/02/docker/</link><pubDate>Thu, 02 Dec 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/12/02/docker/</guid><description>&lt;p&gt;Docker イメージ、コンテナ、ボリュームのサイズを調べる方法です。&lt;/p&gt;
&lt;p&gt;以下のコマンドでわかります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker system df
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;出力結果&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TYPE TOTAL ACTIVE SIZE RECLAIMABLE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Images &lt;span class="m"&gt;35&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; 26.48GB 24.36GB &lt;span class="o"&gt;(&lt;/span&gt;92%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Containers &lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; 125.5MB 0B &lt;span class="o"&gt;(&lt;/span&gt;0%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Local Volumes &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; 320.1MB 0B &lt;span class="o"&gt;(&lt;/span&gt;0%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Build Cache &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; 0B 0B
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;より詳細に（個別に）知りたい場合は &lt;code&gt;-v&lt;/code&gt; をつけます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker system df -v
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/57430694/is-there-a-way-to-determine-the-size-of-a-docker-volume-on-my-macos-machine" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/57430694/is-there-a-way-to-determine-the-size-of-a-docker-volume-on-my-macos-machine&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>GitLab でリストア後に 500 エラーが表示される</title><link>https://blog.ponkotools.com/posts/2021/11/19/gitlab/</link><pubDate>Fri, 19 Nov 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/11/19/gitlab/</guid><description>&lt;p&gt;GitLab でリストア自体は成功するのですが、特定のページにアクセスすると 500 エラーが表示されました。&lt;/p&gt;
&lt;p&gt;原因は以下と同じでした。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2020/01/gitlab-admin-runners-500.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2020/01/gitlab-admin-runners-500.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上記と同じ方法で解決もしました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://forum.gitlab.com/t/after-restoring-a-backup-project-page-is-not-loading-all-other-pages-are-loading-easily/41447" target="_blank" rel="noopener"
 &gt;https://forum.gitlab.com/t/after-restoring-a-backup-project-page-is-not-loading-all-other-pages-are-loading-easily/41447&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/69525251/when-i-click-a-project-500-whoops-something-went-wrong-on-our-end" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/69525251/when-i-click-a-project-500-whoops-something-went-wrong-on-our-end&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>OpenCV + Gstreamer を使う</title><link>https://blog.ponkotools.com/posts/2021/11/17/opencv-gstreamer/</link><pubDate>Wed, 17 Nov 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/11/17/opencv-gstreamer/</guid><description>&lt;p&gt;OpenCV で GStreamer を使うための Docker コンテナを作成したので、GStreamer を使ってカメラの画像を取得するところまで試してみました。&lt;/p&gt;
&lt;p&gt;Docker コンテナの作成については以下の記事に書いています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/11/opencv-gstreamer.html" target="_blank" rel="noopener"
 &gt;OpenCV + GStreamer の Docker コンテナを作成&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="gstreamer-の基本"&gt;&lt;a href="#gstreamer-%e3%81%ae%e5%9f%ba%e6%9c%ac" class="header-anchor"&gt;&lt;/a&gt;GStreamer の基本
&lt;/h2&gt;&lt;p&gt;私は Gstreamer を今回初めて使いました。&lt;br&gt;
最初、GStreamer のことが全然分からず困っていたのですが、以下の記事がとても参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/saxxos/items/e5b452502ad9aca3c997" target="_blank" rel="noopener"
 &gt;https://qiita.com/saxxos/items/e5b452502ad9aca3c997&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="gstreamer-の動作確認"&gt;&lt;a href="#gstreamer-%e3%81%ae%e5%8b%95%e4%bd%9c%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;GStreamer の動作確認
&lt;/h2&gt;&lt;p&gt;OpenCV を使う前に、まずは GStreamer が使えるかどうか単体で試します。&lt;/p&gt;
&lt;p&gt;ネットワークカメラから RTSP で画像を取得して表示します。&lt;br&gt;
今回は Panasonic のカメラを使いました。&lt;/p&gt;
&lt;p&gt;Docker コンテナ内で以下のコマンドを実行するとウィンドウが立ち上がり、カメラの画像が表示されれば OK です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gst-launch-1.0 rtspsrc location=rtsp://username:password@host/MediaInput/h265 ! decodebin ! autovideosink
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;decodebin&lt;/code&gt; でデコードし、&lt;code&gt;autovideosink&lt;/code&gt; 自動表示（画面上にウィンドウで表示）する感じみたいです。&lt;/p&gt;
&lt;h2 id="opencv-を使う"&gt;&lt;a href="#opencv-%e3%82%92%e4%bd%bf%e3%81%86" class="header-anchor"&gt;&lt;/a&gt;OpenCV を使う
&lt;/h2&gt;&lt;p&gt;上記を踏まえ、OpenCV で GStreamer のクエリを指定する場合は、以下のように記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rtspsrc location=rtsp://username:password@host/MediaInput/h265 ! decodebin ! videoconvert ! appsink&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VideoCapture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_GSTREAMER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;autovideosink&lt;/code&gt; を &lt;code&gt;videoconvert ! appsink&lt;/code&gt; に変更しています。&lt;br&gt;
GStreamer の出力を OpenCV に入力するためには &lt;code&gt;appsink&lt;/code&gt; が必要みたいです。&lt;br&gt;
んで、&lt;code&gt;appsink&lt;/code&gt; に送るためには &lt;code&gt;videoconvert&lt;/code&gt; が必要みたいです。&lt;br&gt;
これで &lt;code&gt;cap.read()&lt;/code&gt; をコールすれば、フレームデータを取得できます。&lt;/p&gt;
&lt;p&gt;ただし、このままだと遅延が酷かったので、&lt;code&gt;latency=0&lt;/code&gt; を追加しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rtspsrc location=rtsp://username:password@host/MediaInput/h265 latency=0 ! decodebin ! videoconvert ! appsink&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VideoCapture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_GSTREAMER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とりあえずはこれで動作確認できました。&lt;/p&gt;
&lt;p&gt;ちなみに、OpenCV を使わずにコンソールで &lt;code&gt;gst-launch-1.0&lt;/code&gt; で直接実行する際に &lt;code&gt;latency=0&lt;/code&gt; を指定すると、画像が乱れてまともに表示されませんでした。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/saxxos/items/e5b452502ad9aca3c997" target="_blank" rel="noopener"
 &gt;https://qiita.com/saxxos/items/e5b452502ad9aca3c997&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/maueki/items/b54cbe5207bb16869756" target="_blank" rel="noopener"
 &gt;https://qiita.com/maueki/items/b54cbe5207bb16869756&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://dev.classmethod.jp/articles/gstreamer-on-macos-video/" target="_blank" rel="noopener"
 &gt;https://dev.classmethod.jp/articles/gstreamer-on-macos-video/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://lifestyletransfer.com/how-to-install-gstreamer-vaapi-plugins-on-ubuntu/" target="_blank" rel="noopener"
 &gt;http://lifestyletransfer.com/how-to-install-gstreamer-vaapi-plugins-on-ubuntu/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>OpenCV + GStreamer の Docker コンテナを作成</title><link>https://blog.ponkotools.com/posts/2021/11/16/opencv-gstreamer-docker/</link><pubDate>Tue, 16 Nov 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/11/16/opencv-gstreamer-docker/</guid><description>&lt;p&gt;OpenCV では既定で ffmpeg が使われます。これを gstreamer を使うように設定変更したかったのですが、gstreamer を使うためには OpenCV を自分でビルドしてインストールする必要があるようです。&lt;br&gt;
なので、OpenCV で gstreamer を使うための Dockerfile を作成しました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;Python 3.8.10&lt;/li&gt;
&lt;li&gt;OpenCV 4.5.3&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="前置き"&gt;&lt;a href="#%e5%89%8d%e7%bd%ae%e3%81%8d" class="header-anchor"&gt;&lt;/a&gt;前置き
&lt;/h2&gt;&lt;p&gt;python で OpenCV を扱う場合、&lt;code&gt;opencv-python&lt;/code&gt; をインストールすれば、OpenCV もインストールされるようです。&lt;br&gt;
試しに以下のコードで OpenCV の情報を確認してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;cv2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__version__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getBuildInformation&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Video I/O&lt;/code&gt; の &lt;code&gt;FFMPEG&lt;/code&gt; が &lt;code&gt;YES&lt;/code&gt; になっており、&lt;code&gt;GStreamer&lt;/code&gt; が &lt;code&gt;NO&lt;/code&gt; になっています。&lt;/p&gt;
&lt;p&gt;これを、ffmpeg を無効にして、gstreamer を有効にするため、自分で OpenCV のビルドを行います。&lt;/p&gt;
&lt;h3 id="注意事項"&gt;&lt;a href="#%e6%b3%a8%e6%84%8f%e4%ba%8b%e9%a0%85" class="header-anchor"&gt;&lt;/a&gt;注意事項
&lt;/h3&gt;&lt;p&gt;せっかく自分で OpenCV をビルドしても、&lt;code&gt;opencv-python&lt;/code&gt; をインストールすると、デフォルトの OpenCV が使われるようでした。&lt;br&gt;
&lt;code&gt;OpenCV&lt;/code&gt; のビルド時に python のパスを適切に設定していれば、&lt;code&gt;opencv-python&lt;/code&gt; をインストールしなくても &lt;code&gt;import cv2&lt;/code&gt; が使えるはずなので、&lt;code&gt;opencv-python&lt;/code&gt; はインストールしないようにします。&lt;/p&gt;
&lt;h2 id="適当な-dockerfile-を用意"&gt;&lt;a href="#%e9%81%a9%e5%bd%93%e3%81%aa-dockerfile-%e3%82%92%e7%94%a8%e6%84%8f" class="header-anchor"&gt;&lt;/a&gt;適当な Dockerfile を用意
&lt;/h2&gt;&lt;p&gt;今回は &lt;code&gt;Ubuntu:20.04&lt;/code&gt; のイメージを使いました。&lt;/p&gt;
&lt;h2 id="インストール手順"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e6%89%8b%e9%a0%86" class="header-anchor"&gt;&lt;/a&gt;インストール手順
&lt;/h2&gt;&lt;p&gt;GStreamer と OpenCV の公式のドキュメントが以下になります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gstreamer.freedesktop.org/documentation/installing/on-linux.html" target="_blank" rel="noopener"
 &gt;https://gstreamer.freedesktop.org/documentation/installing/on-linux.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.opencv.org/master/d2/de6/tutorial_py_setup_in_ubuntu.html" target="_blank" rel="noopener"
 &gt;https://docs.opencv.org/master/d2/de6/tutorial_py_setup_in_ubuntu.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これを参考にインストールしていきます。&lt;/p&gt;
&lt;h2 id="最終的に作成した-dockerfile"&gt;&lt;a href="#%e6%9c%80%e7%b5%82%e7%9a%84%e3%81%ab%e4%bd%9c%e6%88%90%e3%81%97%e3%81%9f-dockerfile" class="header-anchor"&gt;&lt;/a&gt;最終的に作成した Dockerfile
&lt;/h2&gt;&lt;p&gt;大体以下のような感じになりました。&lt;br&gt;
途中参考になったページの URL などをソース内にメモしています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ubuntu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;20.04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# tzdataのタイムゾーン入力を求められないようにする&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://tmyoda.hatenablog.com/entry/20210124/1611416396&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ENV&lt;/span&gt; &lt;span class="n"&gt;TZ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Asia&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Tokyo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;ln&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;snf&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;share&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;zoneinfo&lt;/span&gt;&lt;span class="o"&gt;/$&lt;/span&gt;&lt;span class="n"&gt;TZ&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;localtime&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;TZ&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;software&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;common&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 必要なパッケージをインストール（必要に応じて取捨選択）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libgl1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mesa&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libsm6&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;git&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;wget&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;unzip&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# OpenCV: Required build dependencies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cmake&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;numpy&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libavcodec&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libavformat&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libswscale&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libgtk2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libgtk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# OpenCV: Optional Dependencies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libpng&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libjpeg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libopenexr&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libtiff&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libwebp&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# OpenCV のビルド時に -D WITH_QT=ON を設定するために以下が必要だった&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;qtbase5&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;qtdeclarative5&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# gstreamer のインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# https://gstreamer.freedesktop.org/documentation/installing/on-linux.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libgstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libgstreamer&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;base1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libgstreamer&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bad1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;good&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bad&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ugly&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;libav&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;alsa&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;gl&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;gtk3&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;qt5&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gstreamer1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pulseaudio&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# aptのクリア&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rf&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lists&lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# OpenCV のビルドとインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://docs.opencv.org/master/d2/de6/tutorial_py_setup_in_ubuntu.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://toriten1024.hatenablog.com/entry/2018/09/29/012205&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://dlrecord.hatenablog.com/entry/2017/12/15/145356&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://atmarkit.itmedia.co.jp/ait/articles/1704/10/news134.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;mkdir&lt;/span&gt; &lt;span class="n"&gt;opencv&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# OpenCV のダウンロード&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;wget&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;archive&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;unzip&lt;/span&gt; &lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# OpenCV の cmake&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mkdir&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cmake&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;CMAKE_BUILD_TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;RELEASE&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;BUILD_DOCS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OFF&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;BUILD_EXAMPLES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OFF&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;BUILD_TESTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OFF&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;WITH_1394&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OFF&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;WITH_GSTREAMER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ON&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;WITH_FFMPEG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OFF&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# cv2.waitKey() を使うためには WITH_QT=ON にする必要があった&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="n"&gt;WITH_QT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ON&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# OpenCV のビルド ※ $(nproc) はコア数を返す、make を並列処理させて高速化したい場合は指定する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#make -j${nproc} &amp;amp;&amp;amp; \&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#make -j3 &amp;amp;&amp;amp; \&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 後始末&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rf&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opencv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 必要なプラグインをインストール（必要に応じて取捨選択）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;pip3&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pyyaml&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pymongo&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;flask&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pytest&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mongomock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# bash起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/bin/bash&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="docker-コンテナの起動"&gt;&lt;a href="#docker-%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e3%81%ae%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;Docker コンテナの起動
&lt;/h2&gt;&lt;p&gt;上記で作成した Dockerfile をビルドしたらコンテナを起動します。&lt;br&gt;
カメラにアクセスできるよういろいろ指定していますが、ここらへんは環境に応じて変更してください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;xhost +local:docker
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -it --rm \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --name containername \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e DISPLAY=${DISPLAY} \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /tmp/.X11-unix/:/tmp/.X11-unix/ \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /dev/bus/usb:/dev/bus/usb \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --privileged --device /dev/dri:/dev/dri \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --device-cgroup-rule=&amp;#39;c 189:* rmw&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v $(pwd)/workspace:/workspace \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --workdir=&amp;#34;/workspace&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; imagename:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;実際に OpenCV と GStreamer が使えるかどうかの動作確認に別の記事で書きました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/11/opencv-gstreamer_17.html" target="_blank" rel="noopener"
 &gt;OpenCV + Gstreamer を使う&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gstreamer.freedesktop.org/documentation/installing/on-linux.html?gi-language=cc" target="_blank" rel="noopener"
 &gt;https://gstreamer.freedesktop.org/documentation/installing/on-linux.html?gi-language=cc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://doitu.info/blog/448768ab50ca208f7648018a6a4ea9f1ef7b1311" target="_blank" rel="noopener"
 &gt;https://doitu.info/blog/448768ab50ca208f7648018a6a4ea9f1ef7b1311&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/opencv/opencv-python" target="_blank" rel="noopener"
 &gt;https://github.com/opencv/opencv-python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://atmarkit.itmedia.co.jp/ait/articles/1704/10/news134.html" target="_blank" rel="noopener"
 &gt;https://atmarkit.itmedia.co.jp/ait/articles/1704/10/news134.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/jeankenshow/items/01948b2103dff3fc9e5f" target="_blank" rel="noopener"
 &gt;https://qiita.com/jeankenshow/items/01948b2103dff3fc9e5f&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Node.js で `Unexpected end of json input` のエラーがでた</title><link>https://blog.ponkotools.com/posts/2021/11/12/nodejs/</link><pubDate>Fri, 12 Nov 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/11/12/nodejs/</guid><description>&lt;p&gt;Node.js でJSON データを受信してパースしようとしたら &lt;code&gt;Unexpected end of json input&lt;/code&gt; のエラーが表示されました。&lt;/p&gt;
&lt;p&gt;最初以下のように書いていたのですが、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;response.on(&amp;#39;data&amp;#39;, (data) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; let json = JSON.parse(data);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;データが大きい場合は分割されて送信されてくるようなので、以下のように処理すれば上手くいきました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;let chunks = [];
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;response.on(&amp;#39;data&amp;#39;, (data) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; chunks.push(data);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;response.on(&amp;#39;end&amp;#39;, () =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; let data = Buffer.concat(chunks);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; let json = JSON.parse(data);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/45029826/unexpected-end-of-json-input-in-node-js" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/45029826/unexpected-end-of-json-input-in-node-js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>docker-compose でアプリの起動を遅らせる</title><link>https://blog.ponkotools.com/posts/2021/11/08/docker-compose/</link><pubDate>Mon, 08 Nov 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/11/08/docker-compose/</guid><description>&lt;p&gt;docker-compose.yml の &lt;code&gt;depends_on&lt;/code&gt; はあくまでコンテナの依存関係だけであり、アプリの起動や初期化までは待ってくれません。&lt;/p&gt;
&lt;p&gt;現在の docker-compose には &lt;code&gt;condition&lt;/code&gt; というのがあり、コンテナの状態をチェックして起動を制御することが可能なようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gotohayato.com/content/533/" target="_blank" rel="noopener"
 &gt;https://gotohayato.com/content/533/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/shiena/items/47437f4f7874bf70d664" target="_blank" rel="noopener"
 &gt;https://qiita.com/shiena/items/47437f4f7874bf70d664&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ただ、そのために healthcheck の方法を定義しないといけないなどちょっと面倒だったので、今回は &lt;code&gt;sleep&lt;/code&gt; を入れて無理やり起動を遅らせる方法をとりました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sleep&lt;/code&gt; の入れ方ですが、以下の２つの方法を思いつきました。&lt;/p&gt;
&lt;h2 id="command-で指定する例"&gt;&lt;a href="#command-%e3%81%a7%e6%8c%87%e5%ae%9a%e3%81%99%e3%82%8b%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;command で指定する例
&lt;/h2&gt;&lt;p&gt;docker-compose.yml の &lt;code&gt;command&lt;/code&gt; で以下のように記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;command: bash -c &amp;#34;sleep 5 &amp;amp;&amp;amp; python3 sample.py&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="entrypoint-で指定"&gt;&lt;a href="#entrypoint-%e3%81%a7%e6%8c%87%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;entrypoint で指定
&lt;/h2&gt;&lt;p&gt;docker-compose.yml の &lt;code&gt;entrypoint&lt;/code&gt; で起動時に実行するスクリプトファイルを指定し、そのスクリプトファイルの中で &lt;code&gt;sleep&lt;/code&gt; を実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;entrypoint: &amp;#34;/hoge/entrypoint.sh&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gotohayato.com/content/533/" target="_blank" rel="noopener"
 &gt;https://gotohayato.com/content/533/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/shiena/items/47437f4f7874bf70d664" target="_blank" rel="noopener"
 &gt;https://qiita.com/shiena/items/47437f4f7874bf70d664&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://forums.balena.io/t/docker-compose-startup-delay/100607" target="_blank" rel="noopener"
 &gt;https://forums.balena.io/t/docker-compose-startup-delay/100607&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>docker-compose で GPU を使う</title><link>https://blog.ponkotools.com/posts/2021/11/02/docker-compose/</link><pubDate>Tue, 02 Nov 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/11/02/docker-compose/</guid><description>&lt;p&gt;&lt;code&gt;docker run&lt;/code&gt; では &lt;code&gt;--gpus all&lt;/code&gt; としていたのですが、docker-compose ではどう指定すればいいのかわからなかったので調べてみました。&lt;/p&gt;
&lt;p&gt;基本的には以下に書かれている通りです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/compose/gpu-support/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/compose/gpu-support/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;docker-compose では例えば以下のように記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;deploy:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; resources:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; reservations:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; devices:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - capabilities: [gpu]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;environment: 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - NVIDIA_VISIBLE_DEVICES=all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - NVIDIA_DRIVER_CAPABILITIES=all
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/compose/gpu-support/" target="_blank" rel="noopener"
 &gt;https://docs.docker.com/compose/gpu-support/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/66298638/devices-properties-is-not-allowed-while-creating-docker-compose-with-nvidia" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/66298638/devices-properties-is-not-allowed-while-creating-docker-compose-with-nvidia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/1024chon/items/4aaf4c1493fc9200cadc" target="_blank" rel="noopener"
 &gt;https://qiita.com/1024chon/items/4aaf4c1493fc9200cadc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>docker-compose での環境変数の参照方法</title><link>https://blog.ponkotools.com/posts/2021/10/29/docker-compose/</link><pubDate>Fri, 29 Oct 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/10/29/docker-compose/</guid><description>&lt;p&gt;docker コンテナ内でホストと同じユーザーIDを指定するために、ホストの環境変数を参照していました。&lt;/p&gt;
&lt;p&gt;例えば、docker コンテナ内でホストと同じユーザーIDを指定するために以下のように記述していましたが、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -it \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e LOCAL_UID=$(id -u $USER) \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e LOCAL_GID=$(id -g $USER) \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; hoge:0 bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これを docker-compose.yml ではどう書けばいいのか？
結果的には以下のように記述することで上手くいきました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;environment: 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - LOCAL_UID=${id:-u ${USER}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - LOCAL_GID=${id:-g ${USER}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/reflet/items/a96752b4cd3838ea6932" target="_blank" rel="noopener"
 &gt;https://qiita.com/reflet/items/a96752b4cd3838ea6932&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>ffmpeg で mp4 ファイルを結合する</title><link>https://blog.ponkotools.com/posts/2021/10/28/ffmpeg/</link><pubDate>Thu, 28 Oct 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/10/28/ffmpeg/</guid><description>&lt;p&gt;たくさんの mp4 ファイルを結合したかったので、ffmpeg を使って結合しました。&lt;/p&gt;
&lt;p&gt;やり方としては、まず以下のように結合ファイルの一覧を記述したテキストファイルを用意します。&lt;br&gt;
ここでは &lt;code&gt;filelist.txt&lt;/code&gt; というファイル名で作成しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;file &amp;#39;001.mp4&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;file &amp;#39;002.mp4&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;file &amp;#39;003.mp4&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そして、以下のようにコマンドを実行すれば結合できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ffmpeg -f concat -i filelist.txt -c copy sample.mp4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;しかし、動画ファイルがたくさんある場合など、&lt;code&gt;filelist.txt&lt;/code&gt; を手動で作るのが大変なことがあったので、以下のようなスクリプトを作成しました。&lt;br&gt;
ディレクトリ内を再帰的に探索し、ファイル名順で結合します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;dirname &lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;hoge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;FILELIST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;filelist.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;OUTPUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sample.mp4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; pathfile in &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="se"&gt;\f&lt;/span&gt;ind &lt;span class="nv"&gt;$DIR&lt;/span&gt; -name &lt;span class="s1"&gt;&amp;#39;*.mp4&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sort&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; file &lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="nv"&gt;$pathfile&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; &lt;span class="nv"&gt;$FILELIST&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ffmpeg -f concat -i &lt;span class="nv"&gt;$FILELIST&lt;/span&gt; -c copy &lt;span class="nv"&gt;$OUTPUT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm &lt;span class="nv"&gt;$FILELIST&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://torisky.com/ffmpeg%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E5%8B%95%E7%94%BB%E9%80%A3%E7%B5%90%E3%81%AE%E6%96%B9%E6%B3%95/" target="_blank" rel="noopener"
 &gt;https://torisky.com/ffmpeg%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E5%8B%95%E7%94%BB%E9%80%A3%E7%B5%90%E3%81%AE%E6%96%B9%E6%B3%95/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://teratail.com/questions/49217" target="_blank" rel="noopener"
 &gt;https://teratail.com/questions/49217&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://dacelo.space/linux/entry-979.html" target="_blank" rel="noopener"
 &gt;https://dacelo.space/linux/entry-979.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Windows 10 に XPS ビューワーをインストールする</title><link>https://blog.ponkotools.com/posts/2021/10/25/xps/</link><pubDate>Mon, 25 Oct 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/10/25/xps/</guid><description>&lt;p&gt;以前は標準でインストールされていたような気がするんですが、いつの間にかなくなっていたのでインストールしました。&lt;br&gt;
Windows の「アプリと機能」からインストールできます。&lt;/p&gt;
&lt;p&gt;スタートメニュー &amp;gt; 設定 &amp;gt; アプリ &amp;gt; アプリと機能 &amp;gt; オプション機能 &amp;gt; 機能の追加 &amp;gt; XXPS ビューワー&lt;/p&gt;</description></item><item><title>Rocket.Chat で使用している MongoDB をアップグレードする</title><link>https://blog.ponkotools.com/posts/2021/10/20/rocketchat/</link><pubDate>Wed, 20 Oct 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/10/20/rocketchat/</guid><description>&lt;p&gt;Rocket.Chat をアップグレードしたら、MongoDB をアップグレードするように警告が表示されるようになったので、MongoDB もアップグレードしました。&lt;/p&gt;
&lt;p&gt;アップグレードについては、以下の記事が参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://linuxhandbook.com/mongodb-upgrade-rocket-chat/" target="_blank" rel="noopener"
 &gt;https://linuxhandbook.com/mongodb-upgrade-rocket-chat/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;h3 id="アップグレード前"&gt;&lt;a href="#%e3%82%a2%e3%83%83%e3%83%97%e3%82%b0%e3%83%ac%e3%83%bc%e3%83%89%e5%89%8d" class="header-anchor"&gt;&lt;/a&gt;アップグレード前
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Rocket.Chat 3.10.4&lt;/li&gt;
&lt;li&gt;MongoDB 4.0.22&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="アップグレード後"&gt;&lt;a href="#%e3%82%a2%e3%83%83%e3%83%97%e3%82%b0%e3%83%ac%e3%83%bc%e3%83%89%e5%be%8c" class="header-anchor"&gt;&lt;/a&gt;アップグレード後
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Rocket.Chat 4.0.3&lt;/li&gt;
&lt;li&gt;MongoDB 5.0.3&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="やったこと"&gt;&lt;a href="#%e3%82%84%e3%81%a3%e3%81%9f%e3%81%93%e3%81%a8" class="header-anchor"&gt;&lt;/a&gt;やったこと
&lt;/h2&gt;&lt;h3 id="rocketchat-を-403-にアップグレード"&gt;&lt;a href="#rocketchat-%e3%82%92-403-%e3%81%ab%e3%82%a2%e3%83%83%e3%83%97%e3%82%b0%e3%83%ac%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;Rocket.Chat を 4.0.3 にアップグレード
&lt;/h3&gt;&lt;p&gt;3.10.4 から 4.0.3 へのアップグレードはバージョンを変更するだけでいけました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;docker コンテナ停止&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt; の Rocket.Chat のバージョンを 4.0.3 に変更&lt;/li&gt;
&lt;li&gt;docker コンテナ起動&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;この時点で Rocket.Chat 4.0.3、MongoDB 4.0.22 の組み合わせとなりましたが、以下のメッセージが表示されるようになりました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | +----------------------------------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | SERVER RUNNING |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | +----------------------------------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | Rocket.Chat Version: 4.0.3 |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | NodeJS Version: 12.22.1 - x64 |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | MongoDB Version: 4.0.27 |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | MongoDB Engine: wiredTiger |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | Platform: linux |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | Process Port: 3000 |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | Site URL: http://localhost:3000 |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | ReplicaSet OpLog: Enabled |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | Commit Hash: 6e49fc9466 |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | Commit Branch: HEAD |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | +----------------------------------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | +----------------------------------------------------------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | DEPRECATION |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | +----------------------------------------------------------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | YOUR CURRENT MONGODB VERSION (4.0.22) IS DEPRECATED. |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | IT WILL NOT BE SUPPORTED ON ROCKET.CHAT VERSION 5.0.0 AND GREATER, |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | PLEASE UPGRADE MONGODB TO VERSION 4.2 OR GREATER |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | | |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rocketchat_1 | +----------------------------------------------------------------------+
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MongoDB version 4.0.22 is deprecated, please upgrade your installation.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;MongoDB 4.0 は非推奨なので、4.2 以上へアップグレードするよう促されます。&lt;br&gt;
なので、ついでに最新の 5.0 までアップグレードします。&lt;/p&gt;
&lt;h3 id="mongodb-を-42-にアップグレード"&gt;&lt;a href="#mongodb-%e3%82%92-42-%e3%81%ab%e3%82%a2%e3%83%83%e3%83%97%e3%82%b0%e3%83%ac%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;MongoDB を 4.2 にアップグレード
&lt;/h3&gt;&lt;p&gt;4.0 から 4.2 へのアップグレードは &lt;code&gt;docker-compose.yml&lt;/code&gt; を修正して再起動するだけでいけました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;docker コンテナ停止&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt; の MongoDB のバージョンを 4.0 に変更&lt;/li&gt;
&lt;li&gt;docker コンテナ起動&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mongodb-を-44-にアップグレード"&gt;&lt;a href="#mongodb-%e3%82%92-44-%e3%81%ab%e3%82%a2%e3%83%83%e3%83%97%e3%82%b0%e3%83%ac%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;MongoDB を 4.4 にアップグレード
&lt;/h3&gt;&lt;p&gt;4.2 から 4.4 へのアップグレードは &lt;code&gt;docker-compose.yml&lt;/code&gt; を修正して再起動するだけではだめでした。&lt;br&gt;
先に以下のコマンドを実行する必要があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker exec mongo bash -c &amp;#39;mongo --eval &amp;#34;db.adminCommand( { setFeatureCompatibilityVersion: \&amp;#34;4.2\&amp;#34; } )&amp;#34;&amp;#39;`
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;流れとしては以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;上記のコマンドを実行&lt;/li&gt;
&lt;li&gt;docker コンテナ停止&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt; の MongoDB のバージョンを 4.4 に変更&lt;/li&gt;
&lt;li&gt;docker コンテナ起動&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mongodb-を-50-にアップグレード"&gt;&lt;a href="#mongodb-%e3%82%92-50-%e3%81%ab%e3%82%a2%e3%83%83%e3%83%97%e3%82%b0%e3%83%ac%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;MongoDB を 5.0 にアップグレード
&lt;/h3&gt;&lt;p&gt;先ほどと同じです。&lt;br&gt;
上記のコマンドのバージョンを 4.4 に変更して実行します&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker exec mongo bash -c &amp;#39;mongo --eval &amp;#34;db.adminCommand( { setFeatureCompatibilityVersion: \&amp;#34;4.4\&amp;#34; } )&amp;#34;&amp;#39;`
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;流れとしては以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;上記のコマンドを実行&lt;/li&gt;
&lt;li&gt;docker コンテナ停止&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt; の MongoDB のバージョンを 5.0 に変更&lt;/li&gt;
&lt;li&gt;docker コンテナ起動&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://linuxhandbook.com/mongodb-upgrade-rocket-chat/" target="_blank" rel="noopener"
 &gt;https://linuxhandbook.com/mongodb-upgrade-rocket-chat/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>MongoDB でフィールド同士を比較したい</title><link>https://blog.ponkotools.com/posts/2021/09/27/mongodb/</link><pubDate>Mon, 27 Sep 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/09/27/mongodb/</guid><description>&lt;p&gt;MongoDB の where 句には JavaScript のコードを記述できます。&lt;/p&gt;
&lt;p&gt;コレクション内のフィールドを参照したい場合は、&lt;code&gt;this&lt;/code&gt; または &lt;code&gt;obj&lt;/code&gt; を使うそうで、これを使えばフィールド同士の比較もできます。&lt;/p&gt;
&lt;p&gt;以下、pymongo での記述例です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# sample1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;colname&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;$where&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;this.hoge == this.fuga&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# sample2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;colname&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;$where&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;this[&amp;#34;hoge&amp;#34;] == this[&amp;#34;fuga&amp;#34;]&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# sample3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;colname&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;$where&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;obj.hoge == obj.fuga&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# sample4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;colname&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;$where&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;obj[&amp;#34;hoge&amp;#34;] == obj[&amp;#34;fuga&amp;#34;]&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;尚、Date 型のフィールドでは、同じ値かどうかを比較したい場合にそのまま比較しても一致しません。&lt;br&gt;
例えば、以下のように &lt;code&gt;getTime()&lt;/code&gt; で値型にしたうえで比較するなどの必要があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;colname&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;$where&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;this.hoge.getTime() == this.fuga.getTime()&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.mongodb.com/manual/reference/operator/query/where/" target="_blank" rel="noopener"
 &gt;https://docs.mongodb.com/manual/reference/operator/query/where/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/k-ta-yamada/items/76f0797a3284602ff135" target="_blank" rel="noopener"
 &gt;https://qiita.com/k-ta-yamada/items/76f0797a3284602ff135&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/45844496/pymongo-where-clause-with-a-complex-function" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/45844496/pymongo-where-clause-with-a-complex-function&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>MongoDB で更新後のドキュメントを返したい</title><link>https://blog.ponkotools.com/posts/2021/09/24/mongodb/</link><pubDate>Fri, 24 Sep 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/09/24/mongodb/</guid><description>&lt;p&gt;MongoDB の &lt;code&gt;find_one_and_update&lt;/code&gt; などは、デフォルトでは更新前のドキュメントを返しますが、引数の &lt;code&gt;return_document&lt;/code&gt; を指定することで更新後のドキュメントを返すようにもできます。&lt;/p&gt;
&lt;p&gt;以下、pymongo を使った場合の例です。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;pymongo 3.12.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;hoge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;colname&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_one_and_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;return_document&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ReturnDocument&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AFTER&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html?highlight=find_one_and_update#pymongo.collection.Collection.find_one_and_update" target="_blank" rel="noopener"
 &gt;https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html?highlight=find_one_and_update#pymongo.collection.Collection.find_one_and_update&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/50594471/mongodb-return-both-before-and-after-document" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/50594471/mongodb-return-both-before-and-after-document&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PowerShell] JSON の読み込み</title><link>https://blog.ponkotools.com/posts/2021/09/21/powershell/</link><pubDate>Tue, 21 Sep 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/09/21/powershell/</guid><description>&lt;p&gt;古いスクリプトで設定ファイルを XML で作っていたのですが、JSON に移行したので、JSON の読み込み方法です。&lt;/p&gt;
&lt;p&gt;ファイルの読み込みは &lt;code&gt;Get-Content&lt;/code&gt; を使います。&lt;br&gt;
改行が含まれていても大丈夫なように &lt;code&gt;-Raw&lt;/code&gt; を付けます。&lt;br&gt;
その後、JSON 文字列を &lt;code&gt;ConvertFrom-Json&lt;/code&gt; でオブジェクトに変換します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Get-Content sample.json -Raw | ConvertFrom-Json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;または&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ConvertFrom-Json -InputObject (Get-Content sample.json -Raw)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コメント付きの JSON (JSONC) を読み込みたい場合は、以下のサイトにあるように &lt;code&gt;Where-Object&lt;/code&gt; でコメントを取り除けばいけました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://ascii.jp/elem/000/004/036/4036376/2/" target="_blank" rel="noopener"
 &gt;https://ascii.jp/elem/000/004/036/4036376/2/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://tech.guitarrapc.com/entry/2013/08/10/220803" target="_blank" rel="noopener"
 &gt;https://tech.guitarrapc.com/entry/2013/08/10/220803&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://sevenb.jp/wordpress/ura/2019/09/18/powershell%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%8B%E3%82%89json%E3%82%92%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%82%80/" target="_blank" rel="noopener"
 &gt;https://sevenb.jp/wordpress/ura/2019/09/18/powershell%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%8B%E3%82%89json%E3%82%92%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%82%80/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://ascii.jp/elem/000/004/036/4036376/2/" target="_blank" rel="noopener"
 &gt;https://ascii.jp/elem/000/004/036/4036376/2/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[PowerShell] 文字列が null または空文字かどうか判定する</title><link>https://blog.ponkotools.com/posts/2021/09/20/powershell/</link><pubDate>Mon, 20 Sep 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/09/20/powershell/</guid><description>&lt;p&gt;&lt;code&gt;IsNullOrEmpty&lt;/code&gt; を使うのが簡単です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;if([string]::IsNullOrEmpty($str))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # null または空文字の場合の処理
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>[Node.js] Windows で子プロセスを終了させる方法</title><link>https://blog.ponkotools.com/posts/2021/09/15/nodejs/</link><pubDate>Wed, 15 Sep 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/09/15/nodejs/</guid><description>&lt;p&gt;&lt;code&gt;ChileProcess&lt;/code&gt; で子プロセスを作成した場合、&lt;code&gt;ChildProcess.kill()&lt;/code&gt; でプロセスを終了させることができますが、Windows では効きません。&lt;/p&gt;
&lt;p&gt;じゃあ Windows ではどうやって子プロセスを終了させたらいいんだろうと調べてみたら、以下に解答がありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/23706055/why-can-i-not-kill-my-child-process-in-nodejs-on-windows" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/23706055/why-can-i-not-kill-my-child-process-in-nodejs-on-windows&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;spawn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;child_process&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;taskkill&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/pid&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/f&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/t&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/23706055/why-can-i-not-kill-my-child-process-in-nodejs-on-windows" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/23706055/why-can-i-not-kill-my-child-process-in-nodejs-on-windows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://yohshiy.blog.fc2.com/blog-entry-315.html" target="_blank" rel="noopener"
 &gt;http://yohshiy.blog.fc2.com/blog-entry-315.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://neos21.net/blog/2019/10/21-01.html" target="_blank" rel="noopener"
 &gt;https://neos21.net/blog/2019/10/21-01.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] datetime とタイムゾーンについてのメモ</title><link>https://blog.ponkotools.com/posts/2021/09/13/python/</link><pubDate>Mon, 13 Sep 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/09/13/python/</guid><description>&lt;p&gt;ちょっとはまったのでメモしておきます。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;python 3.8.10&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="navive-と-aware"&gt;&lt;a href="#navive-%e3%81%a8-aware" class="header-anchor"&gt;&lt;/a&gt;navive と aware
&lt;/h2&gt;&lt;p&gt;まず、&lt;code&gt;datetime&lt;/code&gt; 型にはタイムゾーンの情報を持たない &lt;code&gt;naive&lt;/code&gt; と、タイムゾーンの情報を持つ &lt;code&gt;aware&lt;/code&gt; な datetime 型があるようです。&lt;/p&gt;
&lt;h3 id="naive-な-datetime-型"&gt;&lt;a href="#naive-%e3%81%aa-datetime-%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;naive な datetime 型
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;出力結果&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-09-13T15:11:50.968159
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="aware-な-datetime-型"&gt;&lt;a href="#aware-%e3%81%aa-datetime-%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;aware な datetime 型
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;JST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=+&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;JST&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JST&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;出力結果&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;datetime.now&lt;/code&gt; で &lt;code&gt;JST&lt;/code&gt; を指定しているので、文字列で出力したときに &lt;code&gt;+09:00&lt;/code&gt; が付与されています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-09-13T15:12:28.720290+09:00
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="文字列から-datetime-への変換"&gt;&lt;a href="#%e6%96%87%e5%ad%97%e5%88%97%e3%81%8b%e3%82%89-datetime-%e3%81%b8%e3%81%ae%e5%a4%89%e6%8f%9b" class="header-anchor"&gt;&lt;/a&gt;文字列から datetime への変換
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2021-09-13T15:11:50.968159&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromisoformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2021-09-13T15:12:28.720290+09:00&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromisoformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;出力結果&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;文字列にタイムゾーンに関する情報がなければ &lt;code&gt;naive&lt;/code&gt;、あれば &lt;code&gt;aware&lt;/code&gt; な &lt;code&gt;datetime&lt;/code&gt; 型になっていることがわかります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-09-13 15:11:50.968159
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-09-13 15:12:28.720290+09:00
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="naive-から-aware-への変換"&gt;&lt;a href="#naive-%e3%81%8b%e3%82%89-aware-%e3%81%b8%e3%81%ae%e5%a4%89%e6%8f%9b" class="header-anchor"&gt;&lt;/a&gt;naive から aware への変換
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;naive&lt;/code&gt; に対して &lt;code&gt;astimezone&lt;/code&gt; でタイムゾーンの情報を付与すると &lt;code&gt;aware&lt;/code&gt; になります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2021-09-13T15:11:50.968159&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromisoformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# naive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;jst_dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tzinfo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# aware&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jst_dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-09-13 15:11:50.968159
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-09-13 15:11:50.968159+00:00
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="utc-から-jst-への変換"&gt;&lt;a href="#utc-%e3%81%8b%e3%82%89-jst-%e3%81%b8%e3%81%ae%e5%a4%89%e6%8f%9b" class="header-anchor"&gt;&lt;/a&gt;UTC から JST への変換
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2021-09-13T15:11:50.968159&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# タイムゾーンの情報がないので、naive な datetime になる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromisoformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# naive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 上記の dt は UTC として解釈する（タイムゾーンを付与する）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;utc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tzinfo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# aware(UTC)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# JST に変換する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;jst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;astimezone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JST&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# aware(JST)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;出力結果&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-09-13 15:11:50.968159
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-09-13 15:11:50.968159+00:00
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-09-14 00:11:50.968159+09:00
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="タイムゾーンのない文字列を-jst-として読み込む"&gt;&lt;a href="#%e3%82%bf%e3%82%a4%e3%83%a0%e3%82%be%e3%83%bc%e3%83%b3%e3%81%ae%e3%81%aa%e3%81%84%e6%96%87%e5%ad%97%e5%88%97%e3%82%92-jst-%e3%81%a8%e3%81%97%e3%81%a6%e8%aa%ad%e3%81%bf%e8%be%bc%e3%82%80" class="header-anchor"&gt;&lt;/a&gt;タイムゾーンのない文字列を JST として読み込む
&lt;/h2&gt;&lt;p&gt;上記の応用で、最初から JST を指定してやると OK です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2021-09-13T15:11:50.968159&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# タイムゾーンの情報がないので、naive な datetime になる&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromisoformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# naive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 上記の dt は JST として解釈する（タイムゾーンを付与する）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;JST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=+&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;JST&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;jst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tzinfo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;JST&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# aware(JST)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;出力結果&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-09-13 15:11:50.968159
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2021-09-13 15:11:50.968159+09:00
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.python.org/ja/3/library/datetime.html" target="_blank" rel="noopener"
 &gt;https://docs.python.org/ja/3/library/datetime.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://zenn.dev/toriwasa/articles/0b842ec4a3cb65" target="_blank" rel="noopener"
 &gt;https://zenn.dev/toriwasa/articles/0b842ec4a3cb65&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/shota243/items/91660ece72b5e84c3adb" target="_blank" rel="noopener"
 &gt;https://qiita.com/shota243/items/91660ece72b5e84c3adb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[JavaScript] JSON の内容を文字列で出力する</title><link>https://blog.ponkotools.com/posts/2021/09/07/javascript/</link><pubDate>Tue, 07 Sep 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/09/07/javascript/</guid><description>&lt;p&gt;オブジェクト単体では何もしなくても文字列で出力されますが、テンプレートリテラルなどを使う場合は &lt;code&gt;JSON.stringify&lt;/code&gt; で JSON 形式の文字列に変換してやる必要があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;hoge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fuga&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;piyo&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hoge: &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`hoge: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;hoge&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`hoge: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fuga&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;piyo&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;hoge&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;hoge&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;hoge&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;fuga&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;piyo&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://hdix.hatenablog.com/entry/2018/01/05/163935" target="_blank" rel="noopener"
 &gt;https://hdix.hatenablog.com/entry/2018/01/05/163935&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[JavaScript] map で配列の値とインデックスを同時に取得する</title><link>https://blog.ponkotools.com/posts/2021/09/03/javascript/</link><pubDate>Fri, 03 Sep 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/09/03/javascript/</guid><description>&lt;p&gt;ずっと C# で Linq を使っていたので、Linq の Select と同じ感覚で JavaScript の map を使うとちょっとはまります。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Node.js v14.17.4&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;h3 id="ダメなパターン"&gt;&lt;a href="#%e3%83%80%e3%83%a1%e3%81%aa%e3%83%91%e3%82%bf%e3%83%bc%e3%83%b3" class="header-anchor"&gt;&lt;/a&gt;ダメなパターン
&lt;/h3&gt;&lt;p&gt;JavaScript にはタプルがないので、Linq の Select と同じように書いてもダメです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;hoge&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;fuga&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;piyo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;targets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[ 0, 1, 2 ]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="解決方法"&gt;&lt;a href="#%e8%a7%a3%e6%b1%ba%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;解決方法
&lt;/h3&gt;&lt;p&gt;以下のようにオブジェクトにして返せば OK です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;hoge&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;fuga&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;piyo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;targets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; { value: &amp;#39;hoge&amp;#39;, index: 0 },
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; { value: &amp;#39;fuga&amp;#39;, index: 1 },
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; { value: &amp;#39;piyo&amp;#39;, index: 2 }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://tkkm.tokyo/post-192/" target="_blank" rel="noopener"
 &gt;https://tkkm.tokyo/post-192/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] http リクエストの送信</title><link>https://blog.ponkotools.com/posts/2021/09/02/python/</link><pubDate>Thu, 02 Sep 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/09/02/python/</guid><description>&lt;p&gt;webapi をたたくときにどうやって書けばいいのか忘れることがあるので、メモしておきます。&lt;/p&gt;
&lt;h2 id="get"&gt;&lt;a href="#get" class="header-anchor"&gt;&lt;/a&gt;GET
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;http://example.com/&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;hoge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="post"&gt;&lt;a href="#post" class="header-anchor"&gt;&lt;/a&gt;POST
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;http://example.com/&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;content-type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;application/json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;json_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;hoge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>VSCode の Remote-Containers を起動したときに、マウントのパスに無効な文字が含まれているというエラーが表示された</title><link>https://blog.ponkotools.com/posts/2021/09/01/vscode/</link><pubDate>Wed, 01 Sep 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/09/01/vscode/</guid><description>&lt;p&gt;ホストのディレクトリをコンテナにマウントしたかったのですが、以下のようなエラーが表示されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker: Error response from daemon: create /home/user/workspace: &amp;#34;/home/user/workspace&amp;#34; includes invalid characters for a local volume name, only &amp;#34;[a-zA-Z0-9][a-zA-Z0-9_.-]&amp;#34; are allowed. If you intended to pass a host directory, use absolute path.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;devcontainer.json&lt;/code&gt; の &lt;code&gt;mounts&lt;/code&gt; の設定は以下です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;mounts&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="s2"&gt;&amp;#34;source=${localWorkspaceFolder}/workspace,target=/workspace&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;type&lt;/code&gt; を省略してしまっていたのですが、&lt;code&gt;type&lt;/code&gt; のデフォルトは &lt;code&gt;volume&lt;/code&gt; なので、ボリュームをマウントしようとしてエラーになっていたみたいです。&lt;br&gt;
以下のように &lt;code&gt;type=bind&lt;/code&gt; を指定したら上手くいきました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;mounts&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="s2"&gt;&amp;#34;source=${localWorkspaceFolder}/workspace,target=/workspace,type=bind&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/microsoft/vscode-remote-release/issues/2573" target="_blank" rel="noopener"
 &gt;https://github.com/microsoft/vscode-remote-release/issues/2573&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://code.visualstudio.com/docs/remote/devcontainerjson-reference" target="_blank" rel="noopener"
 &gt;https://code.visualstudio.com/docs/remote/devcontainerjson-reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Node.js] SQLite + Sequelize で日時の範囲検索</title><link>https://blog.ponkotools.com/posts/2021/08/27/nodejs/</link><pubDate>Fri, 27 Aug 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/08/27/nodejs/</guid><description>&lt;p&gt;DB が SQLite、ORM として Sequelize を使っていますが、日時の範囲検索をしようとしてどのように記述していいのか分からず、ちょっとはまりました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Node.js v14.17.4&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="mailto:sequelize@6.6.5" &gt;sequelize@6.6.5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="mailto:sqlite3@5.0.2" &gt;sqlite3@5.0.2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;where&lt;/code&gt; に指定できる条件として、&lt;code&gt;$gte&lt;/code&gt; とか &lt;code&gt;$lt&lt;/code&gt; とか &lt;code&gt;$between&lt;/code&gt; とかで示している記事がありますが、そのように書いても正しく検索できませんでした。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://sequelize.org/" target="_blank" rel="noopener"
 &gt;最新の公式ドキュメント&lt;/a&gt;を見ると、上記のような記述は見当たらなかったので、&lt;code&gt;Sequelize.Op&lt;/code&gt; を使って記述すると正しく検索できました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;begin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;birthday&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Op&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gte&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Op&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lt&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;条件を動的に記述する場合は以下のようにしたら上手くいきました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;begin&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;birthday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;birthday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Op&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gte&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;begin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;birthday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Op&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lt&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;やっぱ公式のドキュメントは最初にチェックするようにしないとだめですね。&lt;br&gt;
無駄にはまってしまいました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://sequelize.org/master/" target="_blank" rel="noopener"
 &gt;https://sequelize.org/master/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/23403533/how-to-do-query-based-on-date-column-in-sqlite3-using-sequelize" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/23403533/how-to-do-query-based-on-date-column-in-sqlite3-using-sequelize&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Node.js] Express で JSON のリクエストを取得する</title><link>https://blog.ponkotools.com/posts/2021/08/26/nodejs/</link><pubDate>Thu, 26 Aug 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/08/26/nodejs/</guid><description>&lt;p&gt;クライアントから JSON でリクエストを送信しているのに、サーバー側で上手く受信できずちょっとはまりました。&lt;/p&gt;
&lt;p&gt;Express の設定で、JSON のパーサーを指定する必要があるそうです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;express&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;express&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;express&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;express&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urlencoded&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="n"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Content-Type&lt;/code&gt; に &lt;code&gt;application/json&lt;/code&gt; を指定していても、上記の設定を行っていなければリクエストの body が空になって受信できません。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/atlansien/items/c587a0bf2f7f9022107c" target="_blank" rel="noopener"
 &gt;https://qiita.com/atlansien/items/c587a0bf2f7f9022107c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.hrendoh.com/handle-json-requests-and-responses-in-express/" target="_blank" rel="noopener"
 &gt;https://blog.hrendoh.com/handle-json-requests-and-responses-in-express/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>electron で HTTP リクエストを送る</title><link>https://blog.ponkotools.com/posts/2021/08/23/electron/</link><pubDate>Mon, 23 Aug 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/08/23/electron/</guid><description>&lt;p&gt;Node.js の場合は &lt;code&gt;request&lt;/code&gt; モジュールを使って HTTP リクエストを送っていましたが、electron のメインプロセスではどうやって送ればいいんだろうと思って調べてみたら、&lt;code&gt;net&lt;/code&gt; モジュールというのがありました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;electron v13.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="サンプル"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;サンプル
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;net&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;electron&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// リクエストの生成
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;net&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;POST&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;https://example/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;application/json&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;sample&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;sample&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// レスポンス受信時の処理
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;response&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`STATUS: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`HEADERS: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`BODY: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;end&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;No more data in response.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// リクエストの送信
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;サーバー側が Node.js + Express の場合、Body の内容が受信できるようにするには以下の設定が必要です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/08/nodejs-express-json.html" target="_blank" rel="noopener"
 &gt;[Node.js] Express で JSON のリクエストを取得する&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.electronjs.org/docs/api/net" target="_blank" rel="noopener"
 &gt;https://www.electronjs.org/docs/api/net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/44465614/net-request-post-data-not-working" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/44465614/net-request-post-data-not-working&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] Tesseract で OCR を行ったら `UnicodeEncodeError: 'ascii' codec can't encode characters` のエラーが表示された</title><link>https://blog.ponkotools.com/posts/2021/08/22/python/</link><pubDate>Sun, 22 Aug 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/08/22/python/</guid><description>&lt;p&gt;タイトルの通りです。&lt;/p&gt;
&lt;p&gt;よくわかりませんが、UTF-8 の文字を Ascii で出力しようとしてエラーが発生している？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/tesseract-ocr/tesstrain/issues/26" target="_blank" rel="noopener"
 &gt;https://github.com/tesseract-ocr/tesstrain/issues/26&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;とりあえず以下の環境変数を設定したら解消しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;PYTHONIOENCODING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;utf8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/tesseract-ocr/tesstrain/issues/26" target="_blank" rel="noopener"
 &gt;https://github.com/tesseract-ocr/tesstrain/issues/26&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] 文字列の判定で、None と空文字を同時に判定する</title><link>https://blog.ponkotools.com/posts/2021/08/20/python/</link><pubDate>Fri, 20 Aug 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/08/20/python/</guid><description>&lt;p&gt;変数の値が、&lt;code&gt;None&lt;/code&gt; または空文字 &lt;code&gt;''&lt;/code&gt; かどうかの判定を行う方法です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# str が None または空文字の場合に実行される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# str が None でも空文字でもない場合に実行される&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/9573244/how-to-check-if-the-string-is-empty" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/9573244/how-to-check-if-the-string-is-empty&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[JavaScript] コンストラクタで await したい</title><link>https://blog.ponkotools.com/posts/2021/08/19/javascript/</link><pubDate>Thu, 19 Aug 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/08/19/javascript/</guid><description>&lt;p&gt;コンストラクタには &lt;code&gt;async&lt;/code&gt; を指定できないため、通常はコンストラクタ内で &lt;code&gt;await&lt;/code&gt; することができません。&lt;/p&gt;
&lt;p&gt;ググってみるといろいろな対処法が出てきますが、とりあえず私の場合は以下のように無名関数を使って実装しました。&lt;br&gt;
node.js v14.17.4 で確認しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;SampleClass&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;hoge&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/xx2xyyy/items/5ca790efe3e07a92e865" target="_blank" rel="noopener"
 &gt;https://qiita.com/xx2xyyy/items/5ca790efe3e07a92e865&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://var.blog.jp/archives/76837656.html" target="_blank" rel="noopener"
 &gt;http://var.blog.jp/archives/76837656.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://puyobyee18.hatenablog.com/entry/2020/07/03/155002" target="_blank" rel="noopener"
 &gt;https://puyobyee18.hatenablog.com/entry/2020/07/03/155002&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://deep.tacoskingdom.com/blog/23" target="_blank" rel="noopener"
 &gt;https://deep.tacoskingdom.com/blog/23&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[python] MongoDB を操作する</title><link>https://blog.ponkotools.com/posts/2021/08/10/python/</link><pubDate>Tue, 10 Aug 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/08/10/python/</guid><description>&lt;p&gt;pymongo を使って MongoDB を操作します。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;python 3.8.10&lt;/li&gt;
&lt;li&gt;pymongo 3.12.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="インストール"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;インストール
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;pip3&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;pymongo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="クライアントの作成"&gt;&lt;a href="#%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;クライアントの作成
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pymongo&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MongoClient&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;username&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;password&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;192.168.0.1&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;27017&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MongoClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mongodb://&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;@&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;db_name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;collection_name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="書き込み"&gt;&lt;a href="#%e6%9b%b8%e3%81%8d%e8%be%bc%e3%81%bf" class="header-anchor"&gt;&lt;/a&gt;書き込み
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert_one&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;hoge&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;fuga&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;datetime&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="読み込み"&gt;&lt;a href="#%e8%aa%ad%e3%81%bf%e8%be%bc%e3%81%bf" class="header-anchor"&gt;&lt;/a&gt;読み込み
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;find_one()&lt;/code&gt; で一番最初のデータ（一番古いデータ）が取得できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fine_one&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{&amp;#39;_id&amp;#39;: ObjectId(&amp;#39;611209607654c9fcf3e8cf0b&amp;#39;), &amp;#39;hoge&amp;#39;: &amp;#39;fuga&amp;#39;, &amp;#39;datetime&amp;#39;: datetime.datetime(2021, 8, 10, 14, 6, 40, 659000)}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="id-を指定して読み込み"&gt;&lt;a href="#id-%e3%82%92%e6%8c%87%e5%ae%9a%e3%81%97%e3%81%a6%e8%aa%ad%e3%81%bf%e8%be%bc%e3%81%bf" class="header-anchor"&gt;&lt;/a&gt;ID を指定して読み込み
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bson.objectid&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ObjectId&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;611209607654c9fcf3e8cf0b&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_one&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;_id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ObjectId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;出力は上記と同じです。&lt;/p&gt;
&lt;h2 id="削除"&gt;&lt;a href="#%e5%89%8a%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;削除
&lt;/h2&gt;&lt;h3 id="全ドキュメントの削除"&gt;&lt;a href="#%e5%85%a8%e3%83%89%e3%82%ad%e3%83%a5%e3%83%a1%e3%83%b3%e3%83%88%e3%81%ae%e5%89%8a%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;全ドキュメントの削除
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete_many&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.finddevguides.com/Python-mongodb-delete-document" target="_blank" rel="noopener"
 &gt;https://www.finddevguides.com/Python-mongodb-delete-document&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/bc_yuuuuuki/items/23fa7ba63399e64cf321" target="_blank" rel="noopener"
 &gt;https://qiita.com/bc_yuuuuuki/items/23fa7ba63399e64cf321&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://pymongo.readthedocs.io/en/stable/tutorial.html" target="_blank" rel="noopener"
 &gt;https://pymongo.readthedocs.io/en/stable/tutorial.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[python] ネットワークカメラの画像を RTSP で取得して表示・保存</title><link>https://blog.ponkotools.com/posts/2021/08/03/python/</link><pubDate>Tue, 03 Aug 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/08/03/python/</guid><description>&lt;p&gt;やり方はいろいろあると思いますが、OpenCV を使えば簡単にできました。&lt;/p&gt;
&lt;h2 id="画像を取得して表示"&gt;&lt;a href="#%e7%94%bb%e5%83%8f%e3%82%92%e5%8f%96%e5%be%97%e3%81%97%e3%81%a6%e8%a1%a8%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;画像を取得して表示
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;VideoCapture&lt;/code&gt; の引数に RTSP の URL を記述するだけで簡単に画像を取得できます。&lt;br&gt;
URL はネットワークカメラの仕様を確認してください。&lt;br&gt;
今回は Panasonic のカメラを使いました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;cv2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;admin&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;user_pw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;password&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;192.168.0.1&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VideoCapture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;rtsp://&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_pw&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/MediaInput/h264&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;imshow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;VIDEO&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;waitKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;KeyboardInterrupt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;destroyAllWindows&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;VideoCapture の引数を変更すれば、USB カメラや動画ファイルの読み込み、連番のJPGファイルも一括で読み込めたりするので便利です。&lt;/p&gt;
&lt;h2 id="保存"&gt;&lt;a href="#%e4%bf%9d%e5%ad%98" class="header-anchor"&gt;&lt;/a&gt;保存
&lt;/h2&gt;&lt;p&gt;今回 RTSP では H.264 で取得しましたが、フレームの処理は OpenCV 側で上手く処理してくれているので、キーフレームとか GOP とか何も考えずに保存できます。&lt;/p&gt;
&lt;h3 id="jpg-の保存"&gt;&lt;a href="#jpg-%e3%81%ae%e4%bf%9d%e5%ad%98" class="header-anchor"&gt;&lt;/a&gt;JPG の保存
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cv2.imwrite(&amp;#34;sample.jpg&amp;#34;, frame)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="動画の保存"&gt;&lt;a href="#%e5%8b%95%e7%94%bb%e3%81%ae%e4%bf%9d%e5%ad%98" class="header-anchor"&gt;&lt;/a&gt;動画の保存
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;VideoWriter_fourcc&lt;/code&gt; でコーデックを指定します。&lt;br&gt;
以下が参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/Gyutan/items/e279e8680b90ca891250" target="_blank" rel="noopener"
 &gt;https://qiita.com/Gyutan/items/e279e8680b90ca891250&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;画像サイズはキャプチャから取得できる値をそのまま保存時にも使っていますが、フレームレートは取得できないので、直接指定しています。&lt;br&gt;
これが合っていないと当然おかしなことになります（早送り再生やスロー再生したような状態になります）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;import cv2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;user_id = &amp;#34;admin&amp;#34; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;user_pw = &amp;#34;password&amp;#34; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;host = &amp;#34;192.168.0.1&amp;#34; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cap = cv2.VideoCapture(f&amp;#34;rtsp://{user_id}:{user_pw}@{host}/MediaInput/h264&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fmt = cv2.VideoWriter_fourcc(*&amp;#39;MP4V&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;frame_rate = 30.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;writer = cv2.VideoWriter(&amp;#34;sample.mp4&amp;#34;, fmt, frame_rate, (int(width), int(height)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;while(True):
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; try:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ret, frame = cap.read()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; if ret == True:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; writer.write(frame)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cv2.imshow(&amp;#39;VIDEO&amp;#39;, frame)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cv2.waitKey(1)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; except KeyboardInterrupt:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; print(&amp;#34;KeyboardInterrupt&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; break
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;writer.release()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cap.release()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cv2.destroyAllWindows()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/gao_gao/items/3b5485695b464aa789df" target="_blank" rel="noopener"
 &gt;https://qiita.com/gao_gao/items/3b5485695b464aa789df&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://rikoubou.hatenablog.com/entry/2019/01/15/174751" target="_blank" rel="noopener"
 &gt;https://rikoubou.hatenablog.com/entry/2019/01/15/174751&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/Gyutan/items/e279e8680b90ca891250" target="_blank" rel="noopener"
 &gt;https://qiita.com/Gyutan/items/e279e8680b90ca891250&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>例外はいつ使うか？</title><link>https://blog.ponkotools.com/posts/2021/07/11/exception/</link><pubDate>Sun, 11 Jul 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/07/11/exception/</guid><description>&lt;p&gt;今までなんとなくで例外を使っていましたが、達人プログラマーという書籍に一つの考え方があったのでメモ。&lt;/p&gt;
&lt;p&gt;以下のような記述がありました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;「すべての例外ハンドラを除去しても、このプログラムは動作可能だろうか？」と自問してください。答えが「ノー」であれば、例外ではない状況下で例外が使われているはずです。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;つまり、&lt;code&gt;try-catch&lt;/code&gt; 文をなくしても基本的に動作可能であれば良し。&lt;br&gt;
そうでないならば、普通に起こりえる状況に対しても例外で処理してしまっている（例外ではない状況で例外を使ってしまっている）。&lt;/p&gt;
&lt;p&gt;具体的な例として、ファイルオープンの際にファイルが存在しなかった場合が挙げられています。&lt;/p&gt;
&lt;p&gt;要約すると、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ファイルが存在しないという状況が通常起こりえないのであれば、それは例外として処理すべき&lt;/li&gt;
&lt;li&gt;ファイルが存在しないという状況が普通に起こりえるのであれば、例外ではなくエラーとして処理しておくべき&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;というものです。&lt;/p&gt;</description></item><item><title>git-svn の使い方</title><link>https://blog.ponkotools.com/posts/2021/07/03/git-svn/</link><pubDate>Sat, 03 Jul 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/07/03/git-svn/</guid><description>&lt;p&gt;社内で未だに SVN で開発しているプロダクトがあるので、git-svn を使ってみました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;git 2.25.1&lt;/li&gt;
&lt;li&gt;svn 1.13.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="インストール"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;インストール
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install git-svn
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="クローン"&gt;&lt;a href="#%e3%82%af%e3%83%ad%e3%83%bc%e3%83%b3" class="header-anchor"&gt;&lt;/a&gt;クローン
&lt;/h2&gt;&lt;p&gt;SVN リポジトリを指定してクローンを行います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git svn clone --prefix=svn/ &amp;lt;SVNリポジトリのURL&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;--prefix&lt;/code&gt; は SVN のブランチに接頭辞をつけるオプションで、一般的に付けたほうがよいとされています。&lt;/p&gt;
&lt;p&gt;SVN リポジトリが標準的な構成(trunk, branch, tag) になっている場合は &lt;code&gt;-s&lt;/code&gt; オプションを付けます。&lt;br&gt;
標準的な構成になっていない場合は &lt;code&gt;--trunk&lt;/code&gt; &lt;code&gt;branches&lt;/code&gt; &lt;code&gt;--tags&lt;/code&gt; を使用する。&lt;br&gt;
今回はルートが trunk になっており、ブランチも作成していなかったため、以下のように指定しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git svn clone --trunk=/ --prefix=svn/ &amp;lt;SVNリポジトリのURL&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;試しにブランチを表示してみると、以下のようになっていました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git branch -a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* master
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; remotes/svn/trunk
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="コミット"&gt;&lt;a href="#%e3%82%b3%e3%83%9f%e3%83%83%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;コミット
&lt;/h2&gt;&lt;p&gt;コミットは普通に git を使ってやるのと同じです。&lt;/p&gt;
&lt;h2 id="svn-リポジトリにコミットを反映する"&gt;&lt;a href="#svn-%e3%83%aa%e3%83%9d%e3%82%b8%e3%83%88%e3%83%aa%e3%81%ab%e3%82%b3%e3%83%9f%e3%83%83%e3%83%88%e3%82%92%e5%8f%8d%e6%98%a0%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;SVN リポジトリにコミットを反映する
&lt;/h2&gt;&lt;p&gt;git でのプッシュに該当する操作として、SVNにコミットを行います。&lt;br&gt;
コミット前にリベースで git のコミットをまとめておいたほうがいいかもしれません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git svn dcommit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="svn-リポジトリから最新のデータを取得"&gt;&lt;a href="#svn-%e3%83%aa%e3%83%9d%e3%82%b8%e3%83%88%e3%83%aa%e3%81%8b%e3%82%89%e6%9c%80%e6%96%b0%e3%81%ae%e3%83%87%e3%83%bc%e3%82%bf%e3%82%92%e5%8f%96%e5%be%97" class="header-anchor"&gt;&lt;/a&gt;SVN リポジトリから最新のデータを取得
&lt;/h2&gt;&lt;p&gt;リベースを行うことになるみたいです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git svn rebase
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;尚、これを行うにはワークディレクトリ内の全ての変更がコミットされている必要があるみたいです。
コミットしていない変更があった場合、以下のようなエラーが表示されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/workspace/hoge: needs update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;update-index --refresh: command returned error: 1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.freks.jp/start-git-svn/" target="_blank" rel="noopener"
 &gt;https://blog.freks.jp/start-git-svn/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.wantanblog.com/entry/2019/10/15/220051" target="_blank" rel="noopener"
 &gt;https://www.wantanblog.com/entry/2019/10/15/220051&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>git でコミットを一つにまとめる</title><link>https://blog.ponkotools.com/posts/2021/07/02/git/</link><pubDate>Fri, 02 Jul 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/07/02/git/</guid><description>&lt;p&gt;Ｗindows 環境では TortoiseGit を使っているので GUI で出来るのですが、Ubuntu で使っている RabbitGit では出来なさそうだったので、コマンドでやりました。&lt;/p&gt;
&lt;p&gt;TortoiseGit でのやり方は以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2018/09/tortoisegit.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2018/09/tortoisegit.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="まずログを確認"&gt;&lt;a href="#%e3%81%be%e3%81%9a%e3%83%ad%e3%82%b0%e3%82%92%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;まずログを確認
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git log --oneline
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下のように表示されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5418fe (HEAD -&amp;gt; master) fuga
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;f3896f7 piyo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;af6639b hoge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;b1da633 initial commit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここで３つのコミット（hoge、piyo、fuga のメッセージのやつ）を一つにまとめてみます。&lt;/p&gt;
&lt;h2 id="リベースの開始"&gt;&lt;a href="#%e3%83%aa%e3%83%99%e3%83%bc%e3%82%b9%e3%81%ae%e9%96%8b%e5%a7%8b" class="header-anchor"&gt;&lt;/a&gt;リベースの開始
&lt;/h2&gt;&lt;p&gt;まとめたいコミット群の一つ前のコミットに対してリベースを行います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git rebase -i HEAD~3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;HEAD~3&lt;/code&gt; は &lt;code&gt;HEAD~~~&lt;/code&gt; やハッシュ値でも構いません。&lt;/p&gt;
&lt;p&gt;すると、テキストエディタで編集画面が表示されます。&lt;br&gt;
私の場合は nano で表示されました（vi じゃなくてよかった）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pick af6639b hoge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pick f3896f7 piyo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pick c5418fe fuga
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Rebase b1da633..c5418fe onto b1da633 (3 commands)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Commands:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# p, pick &amp;lt;commit&amp;gt; = use commit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# r, reword &amp;lt;commit&amp;gt; = use commit, but edit the commit message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# e, edit &amp;lt;commit&amp;gt; = use commit, but stop for amending
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# s, squash &amp;lt;commit&amp;gt; = use commit, but meld into previous commit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# f, fixup &amp;lt;commit&amp;gt; = like &amp;#34;squash&amp;#34;, but discard this commit&amp;#39;s log message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# x, exec &amp;lt;command&amp;gt; = run command (the rest of the line) using shell
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# b, break = stop here (continue rebase later with &amp;#39;git rebase --continue&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# d, drop &amp;lt;commit&amp;gt; = remove commit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# l, label &amp;lt;label&amp;gt; = label current HEAD with a name
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# t, reset &amp;lt;label&amp;gt; = reset HEAD to a label
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# m, merge [-C &amp;lt;commit&amp;gt; | -c &amp;lt;commit&amp;gt;] &amp;lt;label&amp;gt; [# &amp;lt;oneline&amp;gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# . create a merge commit using the original merge commit&amp;#39;s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# . message (or the oneline, if no original merge commit was
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# . specified). Use -c &amp;lt;commit&amp;gt; to reword the commit message.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# These lines can be re-ordered; they are executed from top to bottom.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# If you remove a line here THAT COMMIT WILL BE LOST.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# However, if you remove everything, the rebase will be aborted.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Note that empty commits are commented out
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;-i&lt;/code&gt; オプションを指定したので、この画面では Rebase を使って現在と過去の間に残ってるコミットをどう処理するかを聞かれています。&lt;/p&gt;
&lt;p&gt;最新以外の &lt;code&gt;pick&lt;/code&gt; の箇所を &lt;code&gt;s&lt;/code&gt; または &lt;code&gt;squash&lt;/code&gt; に変更します。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;変更前&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pick af6639b hoge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pick f3896f7 piyo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pick c5418fe fuga
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;変更後&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pick af6639b hoge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;s f3896f7 piyo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;s c5418fe fuga
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;保存して終了すると、コミットメッセージの編集画面が開きます。&lt;br&gt;
必要に応じて編集し、終了します。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/takke/items/3400b55becfd72769214" target="_blank" rel="noopener"
 &gt;https://qiita.com/takke/items/3400b55becfd72769214&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://dev-yakuza.posstree.com/git/git-squash/" target="_blank" rel="noopener"
 &gt;https://dev-yakuza.posstree.com/git/git-squash/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>RabbitVCS のインストール</title><link>https://blog.ponkotools.com/posts/2021/07/01/rabbit-vcs/</link><pubDate>Thu, 01 Jul 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/07/01/rabbit-vcs/</guid><description>&lt;p&gt;Windows では TortoiseSVN と TortoiseGit を使っていたので、Linux でも GUI で良いのがないかなと探していたら、RabbitVCS というのが Tortoise に似た感じだったので、インストールしてみました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="インストール"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;インストール
&lt;/h2&gt;&lt;p&gt;以下に説明があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://wiki.rabbitvcs.org/wiki/install/ubuntu" target="_blank" rel="noopener"
 &gt;http://wiki.rabbitvcs.org/wiki/install/ubuntu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下のコマンドを実行するだけでインストールできました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install rabbitvcs-nautilus
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これ一つで &lt;code&gt;RabbitVCS SVN&lt;/code&gt; &lt;code&gt;RabbitVCS Git&lt;/code&gt; &lt;code&gt;RabbitVCS Hg&lt;/code&gt; が使えるようになるっぽい。&lt;/p&gt;
&lt;p&gt;あとはファイル比較用の Meld とかいうツールも勝手に入ってました。&lt;/p&gt;
&lt;p&gt;再起動後には Tortoise と同じように、フォルダにアイコンが表示されるようになっていました。&lt;/p&gt;
&lt;h2 id="所感"&gt;&lt;a href="#%e6%89%80%e6%84%9f" class="header-anchor"&gt;&lt;/a&gt;所感
&lt;/h2&gt;&lt;p&gt;まだ全然使っていませんが、とりあえず最新のコードをプルしたりだとか、コミットログを見たりだとか、ファイルの差分を閲覧する分には困っていません。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://wiki.rabbitvcs.org/wiki/install/ubuntu" target="_blank" rel="noopener"
 &gt;http://wiki.rabbitvcs.org/wiki/install/ubuntu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://ameblo.jp/mizuhokuzuhara/entry-12581847170.html" target="_blank" rel="noopener"
 &gt;https://ameblo.jp/mizuhokuzuhara/entry-12581847170.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[python] Tesseract を使った OCR</title><link>https://blog.ponkotools.com/posts/2021/06/29/tesseract/</link><pubDate>Tue, 29 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/29/tesseract/</guid><description>&lt;p&gt;最も基本的なコードのメモです。&lt;/p&gt;
&lt;h2 id="pyocr-を使ったサンプル"&gt;&lt;a href="#pyocr-%e3%82%92%e4%bd%bf%e3%81%a3%e3%81%9f%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;pyocr を使ったサンプル
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pyocr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# OCR エンジンの取得&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pyocr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_available_tools&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# 今回は Tesseract しかないので、0番目に入っている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ビルダーの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pyocr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;builders&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TextBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tesseract_layout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# デフォルト値は3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#OCR対象の画像ファイルを読み込む&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;test.jpg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#画像から文字を読み込む&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image_to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;jpn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="pytesseract-を使ったサンプル"&gt;&lt;a href="#pytesseract-%e3%82%92%e4%bd%bf%e3%81%a3%e3%81%9f%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;pytesseract を使ったサンプル
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pytesseract&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# pytesseract を使ったサンプル&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#OCR対象の画像ファイルを読み込む&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;test.jpg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#画像から文字を読み込む&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pytesseract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image_to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;jpn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://itport.cloud/?p=8326" target="_blank" rel="noopener"
 &gt;https://itport.cloud/?p=8326&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://rightcode.co.jp/blog/information-technology/python-tesseract-image-processing-ocr" target="_blank" rel="noopener"
 &gt;https://rightcode.co.jp/blog/information-technology/python-tesseract-image-processing-ocr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/morita-toyscreation/items/8b5cc889a162052fe2b1" target="_blank" rel="noopener"
 &gt;https://qiita.com/morita-toyscreation/items/8b5cc889a162052fe2b1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Tesseract が動作する docker イメージを作成する</title><link>https://blog.ponkotools.com/posts/2021/06/28/tesseract/</link><pubDate>Mon, 28 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/28/tesseract/</guid><description>&lt;p&gt;Tesseract を使って OCR を行うための環境を、Docker を使って構築しました。開発言語は Python を想定しています。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dockerfile-の作成"&gt;&lt;a href="#dockerfile-%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;Dockerfile の作成
&lt;/h2&gt;&lt;p&gt;Dockerfile のサンプルです。&lt;/p&gt;
&lt;p&gt;USB カメラのキャプチャ画像に対して OCR を行いたかったので、OpenCV と GUI の表示に必要なパッケージもインストールしています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ubuntu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;20.04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Tesseract、訓練済みモジュール、その他必要なパッケージをインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tesseract&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ocr&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tesseract&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ocr&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;jpn&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;git&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libgl1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mesa&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;libsm6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# python パッケージをインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;pip3&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;pyocr&lt;/span&gt; &lt;span class="n"&gt;pytesseract&lt;/span&gt; &lt;span class="n"&gt;opencv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# aptのクリア&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rf&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lists&lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# bash起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/bin/bash&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これをビルドします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker build -t tesseract-dev .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="コンテナ起動"&gt;&lt;a href="#%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;コンテナ起動
&lt;/h2&gt;&lt;p&gt;以下のようにして起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -it --rm \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --name tesseract-dev \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e DISPLAY=${DISPLAY} \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /tmp/.X11-unix/:/tmp/.X11-unix/ \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --device /dev/video0:/dev/video0 \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; tesseract-dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="確認"&gt;&lt;a href="#%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;確認
&lt;/h3&gt;&lt;p&gt;Tesseract がインストールされていることを確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tesseract 4.1.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; leptonica-1.79.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; libgif 5.1.4 : libjpeg 8d (libjpeg-turbo 2.0.3) : libpng 1.6.37 : libtiff 4.1.0 : zlib 1.2.11 : libwebp 0.6.1 : libopenjp2 2.3.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Found AVX2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Found AVX
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Found FMA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Found SSE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Found libarchive 3.4.0 zlib/1.2.11 liblzma/5.2.4 bz2lib/1.0.8 liblz4/1.9.2 libzstd/1.4.4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ついでに Tesseract で OCR 出来ることを確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ tesseract test.jpg output -l jpn
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://crieit.net/posts/Tesseract-Ubuntu-Docker" target="_blank" rel="noopener"
 &gt;https://crieit.net/posts/Tesseract-Ubuntu-Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://a244.hateblo.jp/entry/2016/07/04/050000" target="_blank" rel="noopener"
 &gt;https://a244.hateblo.jp/entry/2016/07/04/050000&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://cocoinit23.com/docker-opencv-importerror-libgl-so-1-cannot-open-shared-object-file/" target="_blank" rel="noopener"
 &gt;https://cocoinit23.com/docker-opencv-importerror-libgl-so-1-cannot-open-shared-object-file/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://heppoco-cto.com/pip-install-opencv-python%E3%81%A7modulenotfounderror-no-module-named-skbuild%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC/456/" target="_blank" rel="noopener"
 &gt;https://heppoco-cto.com/pip-install-opencv-python%E3%81%A7modulenotfounderror-no-module-named-skbuild%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC/456/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/nishiys/items/3b8c1670891f745c5a81" target="_blank" rel="noopener"
 &gt;https://qiita.com/nishiys/items/3b8c1670891f745c5a81&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/fukasawah/items/99219e1ff7d08915952f" target="_blank" rel="noopener"
 &gt;https://qiita.com/fukasawah/items/99219e1ff7d08915952f&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>OpenVINO で "DeprecationWarning: 'inputs' property of IENetwork class is deprecated. To access DataPtrs user need to use 'input_data' property of InputInfoPtr objects which can be accessed by 'input_info' property." の警告が表示された</title><link>https://blog.ponkotools.com/posts/2021/06/25/openvino/</link><pubDate>Fri, 25 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/25/openvino/</guid><description>&lt;p&gt;OpenVINO を使って推論を行うサンプルプログラムを動かしていると、以下の警告が表示されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;DeprecationWarning: &amp;#39;inputs&amp;#39; property of IENetwork class is deprecated. To access DataPtrs user need to use &amp;#39;input_data&amp;#39; property of InputInfoPtr objects which can be accessed by &amp;#39;input_info&amp;#39; property.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使用している OpenVINO のバージョンは 2021.2 ですが、&lt;code&gt;IEPlugin&lt;/code&gt; が現在の OpenVINO からは削除されていることに関連している？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/openvinotoolkit/cvat/issues/1830" target="_blank" rel="noopener"
 &gt;https://github.com/openvinotoolkit/cvat/issues/1830&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;とりあえず以下のように修正すれば動きました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;修正前&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;input_blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;修正後&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;input_blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_info&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/openvinotoolkit/cvat/issues/1830" target="_blank" rel="noopener"
 &gt;https://github.com/openvinotoolkit/cvat/issues/1830&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>OpenVINO が動作する Docker イメージを作る</title><link>https://blog.ponkotools.com/posts/2021/06/24/openvino/</link><pubDate>Thu, 24 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/24/openvino/</guid><description>&lt;p&gt;Docker Hub に OpenVINO の公式イメージがあるので、それを使って画像解析を行うための開発環境をサクッと構築します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/u/openvino" target="_blank" rel="noopener"
 &gt;https://hub.docker.com/u/openvino&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;いろいろなイメージがありますが、開発用なので、サンプルやデモアプリなども入っている &lt;a class="link" href="https://hub.docker.com/r/openvino/ubuntu18_dev" target="_blank" rel="noopener"
 &gt;openvino/ubuntu18_dev&lt;/a&gt; を使います。&lt;/p&gt;
&lt;p&gt;また、開発言語は Python を想定しています。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;Docker 20.10.2&lt;/li&gt;
&lt;li&gt;Visual Studio Code 1.57.1&lt;/li&gt;
&lt;li&gt;OpenVINO 2021.2&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dockerfile-の作成"&gt;&lt;a href="#dockerfile-%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;Dockerfile の作成
&lt;/h2&gt;&lt;p&gt;公式イメージをそのまま使ってもいいですが、開発用として git や pip などは欲しいので入れておきます。&lt;br&gt;
また、依存パッケージのインストール、サンプルやデモアプリのビルドも済ませておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;openvino&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ubuntu18_dev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;2021.2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;USER&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 依存パッケージのインストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;intel&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;openvino&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;install_dependencies&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;install_openvino_dependencies&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# サンプル、デモアプリのビルド&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;intel&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;openvino&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;inference_engine&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;samples&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cpp&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;build_samples&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;intel&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;openvino&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;inference_engine&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;demos&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;build_demos&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /opt/intel/openvino_2021/deployment_tools/demo にデモアプリがある&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 他に必要なものを適宜インストール&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;wget&lt;/span&gt; &lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;pip3&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;onnxruntime&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;clone&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ultralytics&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;yolov5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# aptのクリア&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;apt&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rf&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lists&lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;USER&lt;/span&gt; &lt;span class="n"&gt;openvino&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# bash起動&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/bin/bash&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これを myopenvino としてビルドしました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker build -t myopenvino:2021.2 .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="コンテナ起動"&gt;&lt;a href="#%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;コンテナ起動
&lt;/h2&gt;&lt;p&gt;例えば、以下のように起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -it --rm \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --name openvino
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e DISPLAY=${DISPLAY} \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /tmp/.X11-unix/:/tmp/.X11-unix/ \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /dev/bus/usb:/dev/bus/usb \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --privileged --device /dev/dri:/dev/dri \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --device-cgroup-rule=&amp;#39;c 189:* rmw&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; myopenvino:2021.2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;-e DISPLAY=${DISPLAY}&lt;/code&gt; と &lt;code&gt;-v /tmp/.X11-unix/:/tmp/.X11-unix/&lt;/code&gt; は推論結果を描画するために指定しています。&lt;br&gt;
&lt;code&gt;-v /dev/bus/usb:/dev/bus/usb&lt;/code&gt; は USB カメラなどを使えるように指定しています。&lt;br&gt;
&lt;code&gt;--privileged&lt;/code&gt; &lt;code&gt;--device /dev/dri:/dev/dri&lt;/code&gt; &lt;code&gt;--device-cgroup-rule='c 189:* rmw'&lt;/code&gt; は GPU や Movidius Myriad などで推論を行う場合にも対応できるように指定しています（全部必要なわけではないと思いますが・・・）。&lt;br&gt;
詳細は以下を参考にしてください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.openvinotoolkit.org/2021.2/openvino_docs_install_guides_installing_openvino_docker_linux.html#use_a_docker_image_for_gpu" target="_blank" rel="noopener"
 &gt;https://docs.openvinotoolkit.org/2021.2/openvino_docs_install_guides_installing_openvino_docker_linux.html#use_a_docker_image_for_gpu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="vscode--remote-containers-で起動できるようにする"&gt;&lt;a href="#vscode--remote-containers-%e3%81%a7%e8%b5%b7%e5%8b%95%e3%81%a7%e3%81%8d%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;VSCode + Remote-Containers で起動できるようにする
&lt;/h2&gt;&lt;p&gt;実際に開発するとなると VSCode でデバッグしたいことが多々あると思うので、Remote-Containers を使って起動できるようにします。&lt;/p&gt;
&lt;p&gt;Dockerfile は上記と同じものを使うとして、&lt;code&gt;devcontainer.json&lt;/code&gt; で上記のコンテナ起動時の引数と同じものを指定すれば OK です。&lt;/p&gt;
&lt;p&gt;例えば、以下のような感じです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&amp;#34;runArgs&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&amp;#34;-e&amp;#34;, &amp;#34;DISPLAY=${env:DISPLAY}&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&amp;#34;--privileged&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&amp;#34;--device&amp;#34;, &amp;#34;/dev/dri:/dev/dri&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	],
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&amp;#34;mounts&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&amp;#34;source=/tmp/.X11-unix/,target=/tmp/.X11-unix/,type=bind&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	 	&amp;#34;source=/dev/bus/usb,target=/dev/bus/usb,type=bind&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	],
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/tset-tset-tset/items/cfdb35f65c13d73ccf4a" target="_blank" rel="noopener"
 &gt;https://qiita.com/tset-tset-tset/items/cfdb35f65c13d73ccf4a&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.openvinotoolkit.org/2021.2/openvino_docs_install_guides_installing_openvino_docker_linux.html#use_a_docker_image_for_gpu" target="_blank" rel="noopener"
 &gt;https://docs.openvinotoolkit.org/2021.2/openvino_docs_install_guides_installing_openvino_docker_linux.html#use_a_docker_image_for_gpu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>VSCode + Remote-Containers で python の開発環境を作成する</title><link>https://blog.ponkotools.com/posts/2021/06/18/vscode/</link><pubDate>Fri, 18 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/18/vscode/</guid><description>&lt;p&gt;VSCode の Remote-Containers を使い、python 開発用の docker コンテナを作成し、そのコンテナ中で python のデバッグをできるようにします。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;Visual Studio Code 1.56.2&lt;/li&gt;
&lt;li&gt;Remote Development 0.21.0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これらはインストールされている前提です。&lt;/p&gt;
&lt;h2 id="設定ファイルの作成"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;設定ファイルの作成
&lt;/h2&gt;&lt;p&gt;コマンドパレットを開いて(&lt;code&gt;Shift + Ctrl + p&lt;/code&gt;)、&lt;code&gt;Remote-Container: Add Development Container Configuration Files&lt;/code&gt; を実行します。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Python3&lt;/code&gt; を選択し、続いて Python のバージョンを選択します。&lt;br&gt;
その後、Node.js をインストールするかどうか表示されますが、今回は必要ないのでチェックを外しました。&lt;/p&gt;
&lt;p&gt;OK を押すと、以下のファイルが作成されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.devcontainer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── devcontainer.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="コンテナ起動"&gt;&lt;a href="#%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e8%b5%b7%e5%8b%95" class="header-anchor"&gt;&lt;/a&gt;コンテナ起動
&lt;/h2&gt;&lt;p&gt;画面左下のマークを押し、&lt;code&gt;Reopen in Container&lt;/code&gt; を選択するとコンテナが起動します。&lt;/p&gt;
&lt;div class="separator" style="clear: both;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioggZB1AZm4gmlWlTjfEs7wm9zOu3doCLKbA_2gRtv_QoJGqNZqRMNW0d_BopWrum1d_qJD1EMaTENBnVhoC2_jn-5MVrPm-N1wAfg61Z3is2FAOoRG0fVUnn2SgkV5df_ualWeD2dIB4/s0/5.png" style="display: block; padding: 1em 0; text-align: center; "&gt;&lt;img alt="" border="0" data-original-height="126" data-original-width="149" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioggZB1AZm4gmlWlTjfEs7wm9zOu3doCLKbA_2gRtv_QoJGqNZqRMNW0d_BopWrum1d_qJD1EMaTENBnVhoC2_jn-5MVrPm-N1wAfg61Z3is2FAOoRG0fVUnn2SgkV5df_ualWeD2dIB4/s0/5.png"/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h2 id="拡張機能のインストール"&gt;&lt;a href="#%e6%8b%a1%e5%bc%b5%e6%a9%9f%e8%83%bd%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;拡張機能のインストール
&lt;/h2&gt;&lt;p&gt;Remote-Containers を使う場合、VSCode の拡張機能もコンテナ用に別途インストールする必要があるみたいです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;devcontainer.json&lt;/code&gt; の &lt;code&gt;extensions&lt;/code&gt; に記載しておけば、コンテナ作成時に自動的に拡張機能もインストールされるようです。&lt;br&gt;
今回は設定ファイル作成時に Python を選択したので、最初から下記の２つが記載されていました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;extensions&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;ms-python.python&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;ms-python.vscode-pylance&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;従って、コンテナを起動した時点で &lt;code&gt;python&lt;/code&gt; と &lt;code&gt;pylance&lt;/code&gt; は最初から入っているはずなのですが、何故か私の環境ではインストールされていません。&lt;/p&gt;
&lt;div class="separator" style="clear: both;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjStQ_qPqostcKQAlkbdceNMbMO-BZNhP0tJreUP2ogN30FZOpjdzVCcu4e2vdAyi_oAjtjM4o7UvYC-sP6SLxwmy5rlr3j3WMBRzV5YDH1IP6ZtDtbNnLRqCA0s5Jb46IaHdyFF7m2_ZE/s448/6.png" style="display: block; padding: 1em 0; text-align: center; "&gt;&lt;img alt="" border="0" height="320" data-original-height="448" data-original-width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjStQ_qPqostcKQAlkbdceNMbMO-BZNhP0tJreUP2ogN30FZOpjdzVCcu4e2vdAyi_oAjtjM4o7UvYC-sP6SLxwmy5rlr3j3WMBRzV5YDH1IP6ZtDtbNnLRqCA0s5Jb46IaHdyFF7m2_ZE/s320/6.png"/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;仕方がないので、手動でインストールしました。&lt;/p&gt;
&lt;h3 id="手動でのインストール"&gt;&lt;a href="#%e6%89%8b%e5%8b%95%e3%81%a7%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;手動でのインストール
&lt;/h3&gt;&lt;p&gt;まず、&lt;code&gt;DEV CONTAINER&lt;/code&gt; のところの雲のアイコンをクリックします。&lt;/p&gt;
&lt;div class="separator" style="clear: both;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPaSkx77AmbCpshhGicXrKyLZ9A_bq461WvDwsNco4naOEuPc_qGgZoyUQ7r-SDlfI37oHdyR3X5OqdfpCGxEoFP1kUfJ7N-8vWt0meJjGzdl9qWNeGiucc0utOiOgXxs3PH0M3a-7RJ8/s0/7.png" style="display: block; padding: 1em 0; text-align: center; "&gt;&lt;img alt="" border="0" data-original-height="78" data-original-width="314" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPaSkx77AmbCpshhGicXrKyLZ9A_bq461WvDwsNco4naOEuPc_qGgZoyUQ7r-SDlfI37oHdyR3X5OqdfpCGxEoFP1kUfJ7N-8vWt0meJjGzdl9qWNeGiucc0utOiOgXxs3PH0M3a-7RJ8/s0/7.png"/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;ローカルにインストールされている拡張機能一覧が表示されるので、コンテナ内にインストールしたい拡張機能にチェックを入れます。&lt;/p&gt;
&lt;div class="separator" style="clear: both;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLy5xEDkJtQf2QhyphenhyphenrIcM24qYggb9utZZoxCAALJmIt932CzZfEKeDfVBahFzr2G_Dm42P5oad2cgrPqT-p7CYFwhYJB0Bs17ECzvAzTkHllag54Ey4oPh75VbYvYtjYaqtF4RcH2qM94o/s605/8.png" style="display: block; padding: 1em 0; text-align: center; "&gt;&lt;img alt="" border="0" width="320" data-original-height="458" data-original-width="605" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLy5xEDkJtQf2QhyphenhyphenrIcM24qYggb9utZZoxCAALJmIt932CzZfEKeDfVBahFzr2G_Dm42P5oad2cgrPqT-p7CYFwhYJB0Bs17ECzvAzTkHllag54Ey4oPh75VbYvYtjYaqtF4RcH2qM94o/s320/8.png"/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;インストールが完了した後は一度 VSCode を再起動したほうがよいかと思います。&lt;/p&gt;
&lt;h2 id="デバッグを開始する"&gt;&lt;a href="#%e3%83%87%e3%83%90%e3%83%83%e3%82%b0%e3%82%92%e9%96%8b%e5%a7%8b%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;デバッグを開始する
&lt;/h2&gt;&lt;p&gt;あとはローカル環境で python のデバッグを行う場合と同じです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2020/01/vscode-python.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2020/01/vscode-python.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/sabure500/items/a117b8a1733193be455f" target="_blank" rel="noopener"
 &gt;https://qiita.com/sabure500/items/a117b8a1733193be455f&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/bigengelt/items/780440a146e6a3bdffd4" target="_blank" rel="noopener"
 &gt;https://qiita.com/bigengelt/items/780440a146e6a3bdffd4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Python] InfluxDB への書き込みを行う</title><link>https://blog.ponkotools.com/posts/2021/06/17/python-influxdb/</link><pubDate>Thu, 17 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/17/python-influxdb/</guid><description>&lt;p&gt;Python で InfluxDB へ書き込みを行う方法です。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Windows 10&lt;/li&gt;
&lt;li&gt;Python 3.8.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ライブラリのインストール"&gt;&lt;a href="#%e3%83%a9%e3%82%a4%e3%83%96%e3%83%a9%e3%83%aa%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;ライブラリのインストール
&lt;/h2&gt;&lt;p&gt;pip でライブラリをインストールします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; pip install influxdb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="サンプルコード"&gt;&lt;a href="#%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%b3%e3%83%bc%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;サンプルコード
&lt;/h2&gt;&lt;p&gt;まずは &lt;code&gt;InfluxDBClient&lt;/code&gt; をインポートして、クライアントを作成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;influxdb&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;InfluxDBClient&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# クライアントの作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;InfluxDBClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8086&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;username&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;password&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;dbname&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="db-の作成"&gt;&lt;a href="#db-%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;DB の作成
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;dbname&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="リテンションポリシーの作成"&gt;&lt;a href="#%e3%83%aa%e3%83%86%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%b3%e3%83%9d%e3%83%aa%e3%82%b7%e3%83%bc%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;リテンションポリシーの作成
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_retention_policy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;rpname&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;30d&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="データの書き込み"&gt;&lt;a href="#%e3%83%87%e3%83%bc%e3%82%bf%e3%81%ae%e6%9b%b8%e3%81%8d%e8%be%bc%e3%81%bf" class="header-anchor"&gt;&lt;/a&gt;データの書き込み
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write_points&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;fields&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;hoge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;hoge&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;measurement&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;piyo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;time&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;tags&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;fuga&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;fuga&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;retention_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;リテンションポリシー名&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://influxdb-python.readthedocs.io/en/latest/api-documentation.html" target="_blank" rel="noopener"
 &gt;https://influxdb-python.readthedocs.io/en/latest/api-documentation.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://hassiweb-programming.blogspot.com/2018/10/how-to-use-python-library-for-influxdb.html" target="_blank" rel="noopener"
 &gt;http://hassiweb-programming.blogspot.com/2018/10/how-to-use-python-library-for-influxdb.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kapibara-sos.net/archives/705" target="_blank" rel="noopener"
 &gt;https://kapibara-sos.net/archives/705&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Linux で USB メモリをマウントする</title><link>https://blog.ponkotools.com/posts/2021/06/16/linux/</link><pubDate>Wed, 16 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/16/linux/</guid><description>&lt;p&gt;Ubuntu とかだと USB メモリを挿したら自動でマウントされるので何も意識しなくもいいのですが、いざ他の Linux で USB メモリを挿したときにマウントってどうやるんだっけ？となったのでメモしておきます。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Wind River Linux&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="マウント方法"&gt;&lt;a href="#%e3%83%9e%e3%82%a6%e3%83%b3%e3%83%88%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;マウント方法
&lt;/h2&gt;&lt;p&gt;USB メモリを挿すと、&lt;code&gt;/dev/sda&lt;/code&gt; とか &lt;code&gt;/dev/sdb&lt;/code&gt; とかいうファイル名で認識されます。&lt;br&gt;
これを &lt;code&gt;/mnt/usb&lt;/code&gt; にマウントしてやります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir /mnt/usb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mount /dev/sdb /mnt/usb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="アンマウント方法"&gt;&lt;a href="#%e3%82%a2%e3%83%b3%e3%83%9e%e3%82%a6%e3%83%b3%e3%83%88%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;アンマウント方法
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ umount /mnt/usb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Python で作成したアプリを単一の実行ファイルにする</title><link>https://blog.ponkotools.com/posts/2021/06/16/python/</link><pubDate>Wed, 16 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/16/python/</guid><description>&lt;p&gt;python で作成したアプリを、他のマシン（ネットに繋がっていなかったり、python のバージョンが異なるマシン）で動作させたかったので、単一の実行ファイルを作成して配布することにしました。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;開発環境：Ubuntu&lt;/li&gt;
&lt;li&gt;実行環境：Wind River Linux&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;要は、Ubuntu で作成したアプリを Wind River Linux で動作させたいだけです&lt;/p&gt;
&lt;h2 id="単一実行ファイルの作成"&gt;&lt;a href="#%e5%8d%98%e4%b8%80%e5%ae%9f%e8%a1%8c%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;単一実行ファイルの作成
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;pyinstaller&lt;/code&gt; をインストールします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pip install pyinstaller
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下のコマンドで単一のファイルが作成できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pyinstaller sample.py --onefile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;dist&lt;/code&gt; フォルダ内にバイナリファイルが作成されています。&lt;/p&gt;
&lt;h2 id="動的リンクエラーを回避する"&gt;&lt;a href="#%e5%8b%95%e7%9a%84%e3%83%aa%e3%83%b3%e3%82%af%e3%82%a8%e3%83%a9%e3%83%bc%e3%82%92%e5%9b%9e%e9%81%bf%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;動的リンクエラーを回避する
&lt;/h2&gt;&lt;p&gt;上記で作成したファイルを実行して動けば何の問題もないのですが、私の場合、実行環境で以下のようなエラーが表示されました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2841&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt; &lt;span class="n"&gt;loading&lt;/span&gt; &lt;span class="n"&gt;Python&lt;/span&gt; &lt;span class="n"&gt;lib&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/tmp/_MEI1GKxS0/libpython3.8.so.1.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dlopen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib64&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;libm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;so&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;GLIBC_2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; not found (required by /tmp/_MEI1GKxS0/libpython3.8.so.1.0)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これについて、以下の記事が参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/kenmaro/items/60438c1659b5598066df" target="_blank" rel="noopener"
 &gt;https://qiita.com/kenmaro/items/60438c1659b5598066df&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回は Ubuntu で作成したものを Wind River で動かしたので、動的リンクでエラーになったようなのですが、&lt;code&gt;StaticX&lt;/code&gt; というツールを使えば静的リンクのみの実行ファイルが作成できるようです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/JonathonReinhart/staticx" target="_blank" rel="noopener"
 &gt;https://github.com/JonathonReinhart/staticx&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="staticx-のインストールと実行"&gt;&lt;a href="#staticx-%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%a8%e5%ae%9f%e8%a1%8c" class="header-anchor"&gt;&lt;/a&gt;StaticX のインストールと実行
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pip install staticx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;尚、環境によっては &lt;code&gt;patchelf&lt;/code&gt; のインストールも必要みたいです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pip install patchelf-wrapper
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;あとは、以下のようにして実行するだけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ staticx &amp;lt;pyinstallerで作成したバイナリファイル&amp;gt; &amp;lt;出力ファイル名&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで作成したファイルを使うと、無事に実行できました。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/hirohiro77/items/466e411fa41f144c8b2a" target="_blank" rel="noopener"
 &gt;https://qiita.com/hirohiro77/items/466e411fa41f144c8b2a&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/kenmaro/items/60438c1659b5598066df" target="_blank" rel="noopener"
 &gt;https://qiita.com/kenmaro/items/60438c1659b5598066df&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[python] ログを syslog に出力する</title><link>https://blog.ponkotools.com/posts/2021/06/15/python-syslog/</link><pubDate>Tue, 15 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/15/python-syslog/</guid><description>&lt;p&gt;python でログをファイルに出力する記事を書きましたが、Linux には syslog があるので、アプリケーションのログも syslog に出力してみます。&lt;/p&gt;
&lt;p&gt;ちなみに前回の記事は&lt;a class="link" href="https://kuttsun.blogspot.com/2021/06/python.html" target="_blank" rel="noopener"
 &gt;こちら&lt;/a&gt;です。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;python 3.8.5&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="とりあえず簡単にやりたいなら"&gt;&lt;a href="#%e3%81%a8%e3%82%8a%e3%81%82%e3%81%88%e3%81%9a%e7%b0%a1%e5%8d%98%e3%81%ab%e3%82%84%e3%82%8a%e3%81%9f%e3%81%84%e3%81%aa%e3%82%89" class="header-anchor"&gt;&lt;/a&gt;とりあえず簡単にやりたいなら
&lt;/h2&gt;&lt;p&gt;以下で OK です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;syslog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;syslog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;syslog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;This is a test message&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;syslog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;syslog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;syslog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LOG_INFO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Test message at INFO priority&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;しかし、これだと syslog 固定なので、ログの出力先を変更したい場合に大変です。&lt;br&gt;
なので、logger を使って抽象化したほうが良いと思います。&lt;/p&gt;
&lt;h2 id="logger-の出力先を-syslog-にする"&gt;&lt;a href="#logger-%e3%81%ae%e5%87%ba%e5%8a%9b%e5%85%88%e3%82%92-syslog-%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;logger の出力先を syslog にする
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DEBUG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SysLogHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/dev/log&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#basicConfig(level=DEBUG, handlers=[handlers.SysLogHandler(address=(&amp;#34;127.0.0.1&amp;#34;,514))])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;MyLogger&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is info&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is debug&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;critical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is critical&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="標準出力にも出力したい"&gt;&lt;a href="#%e6%a8%99%e6%ba%96%e5%87%ba%e5%8a%9b%e3%81%ab%e3%82%82%e5%87%ba%e5%8a%9b%e3%81%97%e3%81%9f%e3%81%84" class="header-anchor"&gt;&lt;/a&gt;標準出力にも出力したい
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;handlers&lt;/code&gt; に &lt;code&gt;StreamHandler&lt;/code&gt; を追加すれば OK です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;StreamHandler&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SysLogHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/dev/log&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#basicConfig(level=DEBUG, handlers=[StreamHandler(), handlers.SysLogHandler(address=(&amp;#34;127.0.0.1&amp;#34;,514))])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;MyLogger&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is info&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is debug&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;critical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is critical&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="docker-コンテナ内のアプリのログをホストの-syslog-に追加する"&gt;&lt;a href="#docker-%e3%82%b3%e3%83%b3%e3%83%86%e3%83%8a%e5%86%85%e3%81%ae%e3%82%a2%e3%83%97%e3%83%aa%e3%81%ae%e3%83%ad%e3%82%b0%e3%82%92%e3%83%9b%e3%82%b9%e3%83%88%e3%81%ae-syslog-%e3%81%ab%e8%bf%bd%e5%8a%a0%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;Docker コンテナ内のアプリのログをホストの syslog に追加する
&lt;/h2&gt;&lt;p&gt;以下の記事で書いています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kuttsun.blogspot.com/2021/12/python-syslog.html" target="_blank" rel="noopener"
 &gt;https://kuttsun.blogspot.com/2021/12/python-syslog.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.python.org/ja/3/library/logging.html" target="_blank" rel="noopener"
 &gt;https://docs.python.org/ja/3/library/logging.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/3968669/how-to-configure-logging-to-syslog-in-python" target="_blank" rel="noopener"
 &gt;https://stackoverflow.com/questions/3968669/how-to-configure-logging-to-syslog-in-python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/amedama/items/b856b2f30c2f38665701" target="_blank" rel="noopener"
 &gt;https://qiita.com/amedama/items/b856b2f30c2f38665701&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.python.org/ja/3/library/syslog.html" target="_blank" rel="noopener"
 &gt;https://docs.python.org/ja/3/library/syslog.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[python] ログをファイルに出力する</title><link>https://blog.ponkotools.com/posts/2021/06/14/python/</link><pubDate>Mon, 14 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/14/python/</guid><description>&lt;p&gt;&lt;code&gt;logger&lt;/code&gt; を使ってログをファイルに出力します。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;python 3.8.5&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="logger-によるログ出力"&gt;&lt;a href="#logger-%e3%81%ab%e3%82%88%e3%82%8b%e3%83%ad%e3%82%b0%e5%87%ba%e5%8a%9b" class="header-anchor"&gt;&lt;/a&gt;logger によるログ出力
&lt;/h2&gt;&lt;p&gt;以下の記事を参考にさせていただきました。&lt;br&gt;
&lt;code&gt;logging&lt;/code&gt; ではなく &lt;code&gt;logger&lt;/code&gt; を使う理由なども書かれています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/amedama/items/b856b2f30c2f38665701" target="_blank" rel="noopener"
 &gt;https://qiita.com/amedama/items/b856b2f30c2f38665701&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DEBUG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;test.log&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hello&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/amedama/items/b856b2f30c2f38665701" target="_blank" rel="noopener"
 &gt;https://qiita.com/amedama/items/b856b2f30c2f38665701&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Grafana のダッシュボードをログインなしで閲覧できるようにする</title><link>https://blog.ponkotools.com/posts/2021/06/11/grafana/</link><pubDate>Fri, 11 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/11/grafana/</guid><description>&lt;p&gt;タイトルの通りです。&lt;/p&gt;
&lt;p&gt;Grafana には一応 Snapshot という機能がありますが、日時の範囲が固定で、範囲を変えても範囲外のデータは閲覧できなかったりと、その名の通りあくまでスナップショットです。&lt;/p&gt;
&lt;p&gt;なので、ログインしなくてもダッシュボードの閲覧だけは出来るように設定します。&lt;/p&gt;
&lt;h2 id="環境"&gt;&lt;a href="#%e7%92%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;環境
&lt;/h2&gt;&lt;p&gt;docker および docker-compose を使って構築しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Grafana v7.5.7&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="設定"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;設定
&lt;/h2&gt;&lt;p&gt;設定方法は &lt;code&gt;grafana.ini&lt;/code&gt; を編集するか、環境変数を設定するかのどちらかで行います。&lt;/p&gt;
&lt;p&gt;今回は docker-compose.yml で環境変数を設定しました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GF_AUTH_ANONYMOUS_ENABLED&lt;/code&gt; を &lt;code&gt;true&lt;/code&gt; に設定すれば、ログインなしでもダッシュボードの閲覧ができるようになります。&lt;/p&gt;
&lt;p&gt;以下、設定例です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;3.1&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;influxdb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;influxdb&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;influxdb:1.8.6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;8086:8086&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;influxdb:/var/lib/influxdb&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;grafana&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;grafana&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;grafana/grafana&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;influxdb&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;3000:3000&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;GF_AUTH_ANONYMOUS_ENABLED=true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;grafana:/var/lib/grafana&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;influxdb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;grafana&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;尚、環境変数の一覧は Grafana の Server Admin &amp;gt; Settings で確認できます。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://uzimihsr.github.io/post/2020-05-08-grafana-anonymous-authentication/" target="_blank" rel="noopener"
 &gt;https://uzimihsr.github.io/post/2020-05-08-grafana-anonymous-authentication/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/ryotaro76/items/22fa5e877eaab8b567e1" target="_blank" rel="noopener"
 &gt;https://qiita.com/ryotaro76/items/22fa5e877eaab8b567e1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>git コマンドのメモ</title><link>https://blog.ponkotools.com/posts/2021/06/07/git/</link><pubDate>Mon, 07 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/07/git/</guid><description>&lt;p&gt;普段は TortoiseGit を使っており、いざコマンドしか使えない環境のときに困るので、個人的によく使う基本的なコマンドについてメモしておきます。&lt;/p&gt;
&lt;p&gt;適宜更新していきます。&lt;/p&gt;
&lt;h2 id="設定"&gt;&lt;a href="#%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;設定
&lt;/h2&gt;&lt;h3 id="現在の設定を確認"&gt;&lt;a href="#%e7%8f%be%e5%9c%a8%e3%81%ae%e8%a8%ad%e5%ae%9a%e3%82%92%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;現在の設定を確認
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;システム全体(&lt;code&gt;system&lt;/code&gt;)、ユーザー全体(&lt;code&gt;global&lt;/code&gt;)、対象リポジトリのみ(&lt;code&gt;local&lt;/code&gt;)を確認したい場合はそれぞれ以下。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --system --list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --global --list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --local --list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ローカルのユーザーとメールアドレスを設定"&gt;&lt;a href="#%e3%83%ad%e3%83%bc%e3%82%ab%e3%83%ab%e3%81%ae%e3%83%a6%e3%83%bc%e3%82%b6%e3%83%bc%e3%81%a8%e3%83%a1%e3%83%bc%e3%83%ab%e3%82%a2%e3%83%89%e3%83%ac%e3%82%b9%e3%82%92%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;ローカルのユーザーとメールアドレスを設定
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --local user.name &amp;#34;My Name&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --local user.email myname@example.com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="リモートリポジトリの情報"&gt;&lt;a href="#%e3%83%aa%e3%83%a2%e3%83%bc%e3%83%88%e3%83%aa%e3%83%9d%e3%82%b8%e3%83%88%e3%83%aa%e3%81%ae%e6%83%85%e5%a0%b1" class="header-anchor"&gt;&lt;/a&gt;リモートリポジトリの情報
&lt;/h3&gt;&lt;p&gt;リモートリポジトリの名前を表示する&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;リモートリポジトリの名前と場所(URL）を表示する&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote -v
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;指定したリモートリポジトリの詳しい情報を表示する&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote show &amp;lt;リポジトリ名&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="リモートリポジトリの追加削除変更"&gt;&lt;a href="#%e3%83%aa%e3%83%a2%e3%83%bc%e3%83%88%e3%83%aa%e3%83%9d%e3%82%b8%e3%83%88%e3%83%aa%e3%81%ae%e8%bf%bd%e5%8a%a0%e5%89%8a%e9%99%a4%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;リモートリポジトリの追加・削除・変更
&lt;/h3&gt;&lt;p&gt;追加する&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote add &amp;lt;リポジトリ名&amp;gt; &amp;lt;URL&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;削除する&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote rm &amp;lt;リポジトリ名&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;URL の変更&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote set-url &amp;lt;リポジトリ名&amp;gt; &amp;lt;変更先のURL&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="開発中に使うコマンド"&gt;&lt;a href="#%e9%96%8b%e7%99%ba%e4%b8%ad%e3%81%ab%e4%bd%bf%e3%81%86%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89" class="header-anchor"&gt;&lt;/a&gt;開発中に使うコマンド
&lt;/h2&gt;&lt;h3 id="クローン"&gt;&lt;a href="#%e3%82%af%e3%83%ad%e3%83%bc%e3%83%b3" class="header-anchor"&gt;&lt;/a&gt;クローン
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git clone &amp;lt;URL&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="差分を表示"&gt;&lt;a href="#%e5%b7%ae%e5%88%86%e3%82%92%e8%a1%a8%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;差分を表示
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git status
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;-s&lt;/code&gt; を使えると簡略化して表示されます。&lt;/p&gt;
&lt;h3 id="コミットの流れ"&gt;&lt;a href="#%e3%82%b3%e3%83%9f%e3%83%83%e3%83%88%e3%81%ae%e6%b5%81%e3%82%8c" class="header-anchor"&gt;&lt;/a&gt;コミットの流れ
&lt;/h3&gt;&lt;h4 id="ステージング"&gt;&lt;a href="#%e3%82%b9%e3%83%86%e3%83%bc%e3%82%b8%e3%83%b3%e3%82%b0" class="header-anchor"&gt;&lt;/a&gt;ステージング
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add ファイル名
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="コミット"&gt;&lt;a href="#%e3%82%b3%e3%83%9f%e3%83%83%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;コミット
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &amp;#34;コメント&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="プッシュ"&gt;&lt;a href="#%e3%83%97%e3%83%83%e3%82%b7%e3%83%a5" class="header-anchor"&gt;&lt;/a&gt;プッシュ
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="最後のコミットのやり直し"&gt;&lt;a href="#%e6%9c%80%e5%be%8c%e3%81%ae%e3%82%b3%e3%83%9f%e3%83%83%e3%83%88%e3%81%ae%e3%82%84%e3%82%8a%e7%9b%b4%e3%81%97" class="header-anchor"&gt;&lt;/a&gt;最後のコミットのやり直し
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit --amend -m &amp;#34;コミットメッセージ&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="変更の破棄"&gt;&lt;a href="#%e5%a4%89%e6%9b%b4%e3%81%ae%e7%a0%b4%e6%a3%84" class="header-anchor"&gt;&lt;/a&gt;変更の破棄
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout &amp;lt;filename&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;全て破棄したい場合は以下&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/shionit/items/fb4a1a30538f8d335b35" target="_blank" rel="noopener"
 &gt;https://qiita.com/shionit/items/fb4a1a30538f8d335b35&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/konweb/items/621722f67fdd8f86a017" target="_blank" rel="noopener"
 &gt;https://qiita.com/konweb/items/621722f67fdd8f86a017&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>AWS CLI のインストールと認証情報の設定</title><link>https://blog.ponkotools.com/posts/2021/06/05/aws/</link><pubDate>Sat, 05 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/05/aws/</guid><description>&lt;p&gt;Windows と Ubuntu で設定しました。&lt;/p&gt;
&lt;h2 id="インストール"&gt;&lt;a href="#%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;インストール
&lt;/h2&gt;&lt;h3 id="windows"&gt;&lt;a href="#windows" class="header-anchor"&gt;&lt;/a&gt;Windows
&lt;/h3&gt;&lt;p&gt;インストーラーをダウンロードしてインストールします。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://awscli.amazonaws.com/AWSCLIV2.msi" target="_blank" rel="noopener"
 &gt;https://awscli.amazonaws.com/AWSCLIV2.msi&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ubuntu-2004"&gt;&lt;a href="#ubuntu-2004" class="header-anchor"&gt;&lt;/a&gt;Ubuntu 20.04
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install awscli
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="認証情報の設定"&gt;&lt;a href="#%e8%aa%8d%e8%a8%bc%e6%83%85%e5%a0%b1%e3%81%ae%e8%a8%ad%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;認証情報の設定
&lt;/h2&gt;&lt;h3 id="アクセスキーの作成"&gt;&lt;a href="#%e3%82%a2%e3%82%af%e3%82%bb%e3%82%b9%e3%82%ad%e3%83%bc%e3%81%ae%e4%bd%9c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;アクセスキーの作成
&lt;/h3&gt;&lt;p&gt;AWS にログインし、IAM を選択します。&lt;br&gt;
メニューより &lt;code&gt;ユーザー&lt;/code&gt; を選択し、&lt;code&gt;認証情報&lt;/code&gt; タブより &lt;code&gt;アクセスキーの作成&lt;/code&gt; をクリックします。&lt;/p&gt;
&lt;p&gt;アクセスキーが作成されたら、ローカルで以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ aws configure
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;AWS Access Key ID [None]: &amp;lt;Access Key&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;AWS Secret Access Key [None]: &amp;lt;Secret Access Key&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Default region name [None]: ap-northeast-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Default output format [None]: json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://dev.classmethod.jp/articles/how-to-install-aws-cli-v2-on-windows/" target="_blank" rel="noopener"
 &gt;https://dev.classmethod.jp/articles/how-to-install-aws-cli-v2-on-windows/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.trainocate.co.jp/blog/aws_auth_022" target="_blank" rel="noopener"
 &gt;https://blog.trainocate.co.jp/blog/aws_auth_022&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[python] 文字列から timedelta に変換</title><link>https://blog.ponkotools.com/posts/2021/06/03/python/</link><pubDate>Thu, 03 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/03/python/</guid><description>&lt;p&gt;文字列から時差などを表す timedelta に変換する方法です。&lt;/p&gt;
&lt;p&gt;コロンで分割して数値にし、&lt;a class="link" href="https://docs.python.org/ja/3/library/datetime.html#timedelta-objects" target="_blank" rel="noopener"
 &gt;timedelta&lt;/a&gt; 型に変換しています。&lt;br&gt;
今回の例では microsecond まで含むので、数値は float 型にしています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1:23:45.678900&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;:&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;td&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;td&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1:23:45.678900
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://ja.stackoverflow.com/questions/56439/%E6%96%87%E5%AD%97%E5%88%97%E3%82%92timedelta-%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95" target="_blank" rel="noopener"
 &gt;https://ja.stackoverflow.com/questions/56439/%E6%96%87%E5%AD%97%E5%88%97%E3%82%92timedelta-%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.python.org/ja/3/library/datetime.html" target="_blank" rel="noopener"
 &gt;https://docs.python.org/ja/3/library/datetime.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Blogger の画像挿入タグが残念すぎるので、CSS で少しだけ対応する</title><link>https://blog.ponkotools.com/posts/2021/06/02/blogger/</link><pubDate>Wed, 02 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/02/blogger/</guid><description>&lt;p&gt;Blogger の記事投稿画面で画像を挿入した場合、以下のようなタグで挿入されます。&lt;/p&gt;
&lt;p&gt;※2021年6月現在の場合&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;separator&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;clear: both;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgshA-sB1IOm4s0JYX1L5iFGbw7ifN15irj6WkGQ2PdJBW5-Ud1zN4YT1vBh7LBTmRhVAGg0ieitP8gUf9WJMDIM9oEN89NhBitkJS_s_zPTJm5FSLeCuSL9znJv6YlQIrEP9kDt7-8ZJs/s868/%25E7%2584%25A1%25E9%25A1%258C.png&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;display: block; padding: 1em 0; text-align: center; &amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;320&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-original-height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;240&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-original-width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;868&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgshA-sB1IOm4s0JYX1L5iFGbw7ifN15irj6WkGQ2PdJBW5-Ud1zN4YT1vBh7LBTmRhVAGg0ieitP8gUf9WJMDIM9oEN89NhBitkJS_s_zPTJm5FSLeCuSL9znJv6YlQIrEP9kDt7-8ZJs/s320/%25E7%2584%25A1%25E9%25A1%258C.png&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;とても残念です。&lt;br&gt;
昔はこんな変なコードじゃなかったけどなぁ（過去の記事を見て確認）。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;a&lt;/code&gt; タグに &lt;code&gt;display: block;&lt;/code&gt; が追加されています。&lt;br&gt;
このせいで、画像の横の余白もクリックできるようになってしまっています。&lt;/p&gt;
&lt;div class="separator" style="clear: both;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgshA-sB1IOm4s0JYX1L5iFGbw7ifN15irj6WkGQ2PdJBW5-Ud1zN4YT1vBh7LBTmRhVAGg0ieitP8gUf9WJMDIM9oEN89NhBitkJS_s_zPTJm5FSLeCuSL9znJv6YlQIrEP9kDt7-8ZJs/s868/%25E7%2584%25A1%25E9%25A1%258C.png" style="display: block; padding: 1em 0; text-align: center; "&gt;&lt;img alt="" border="0" width="320" data-original-height="240" data-original-width="868" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgshA-sB1IOm4s0JYX1L5iFGbw7ifN15irj6WkGQ2PdJBW5-Ud1zN4YT1vBh7LBTmRhVAGg0ieitP8gUf9WJMDIM9oEN89NhBitkJS_s_zPTJm5FSLeCuSL9znJv6YlQIrEP9kDt7-8ZJs/s320/%25E7%2584%25A1%25E9%25A1%258C.png"/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;何もないところをクリックできてしまうことにすごい違和感があります。&lt;/p&gt;
&lt;p&gt;さらに、Blogger はデフォルトでライトボックス機能が有効になっていますが、画像横の余白をクリックした場合はライトボックス機能が効きません。&lt;br&gt;
画像の上をクリックしたときだけ効きます。&lt;/p&gt;
&lt;p&gt;また、上記は配置を中央にしているのですが、これまた &lt;code&gt;a&lt;/code&gt; タグに &lt;code&gt;text-align: center;&lt;/code&gt; が追加されています。&lt;/p&gt;
&lt;p&gt;従って、画像横の余白をクリックできないようにしようと &lt;code&gt;display: block;&lt;/code&gt; を削除すると、&lt;code&gt;text-align: center;&lt;/code&gt; が効かなくなるという残念さ。&lt;/p&gt;
&lt;p&gt;なんで一つ上の &lt;code&gt;div&lt;/code&gt; に設定してくれないんだろう？&lt;br&gt;
というわけで、上記の &lt;code&gt;display: block;&lt;/code&gt; &lt;code&gt;text-align: center;&lt;/code&gt; を &lt;code&gt;div&lt;/code&gt; タグに設定すれば解決します。&lt;/p&gt;
&lt;p&gt;でも、画像挿入の度に手動で変更するのは面倒ですし、過去の記事全部を修正なんてやってられないので、以下の CSS を追加して対応しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;separator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;separator&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;inline&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ただし、画像の配置位置は中央固定です。&lt;/p&gt;
&lt;p&gt;きちんとやろうとすると、&lt;code&gt;a&lt;/code&gt; タグ内の &lt;code&gt;text-align&lt;/code&gt; の値を、親要素の &lt;code&gt;div&lt;/code&gt; に適用させる処理が必要ですが、CSS だけではできないので、JavaScript を使う必要があります。&lt;br&gt;
私はそこまでやりたくなかったので、これで妥協しました。&lt;/p&gt;
&lt;p&gt;もしかしたら、CSS4 になったらできる？&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://teratail.com/questions/51614" target="_blank" rel="noopener"
 &gt;https://teratail.com/questions/51614&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Git で HTTPS を使う場合のアカウント情報を記憶させる</title><link>https://blog.ponkotools.com/posts/2021/06/01/git/</link><pubDate>Tue, 01 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/01/git/</guid><description>&lt;p&gt;毎回打つのが面倒なので。&lt;/p&gt;
&lt;h2 id="windows-の場合"&gt;&lt;a href="#windows-%e3%81%ae%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;Windows の場合
&lt;/h2&gt;&lt;p&gt;クローンするときにユーザー名とパスワードが聞かれますが、一度入力すると資格情報マネージャーに登録されるので、２回目以降はユーザー名とパスワードの入力が不要になります。&lt;br&gt;
もし入力間違いをしてしまった場合は、資格情報マネージャーで削除すれば OK です。&lt;/p&gt;
&lt;h2 id="linux-の場合"&gt;&lt;a href="#linux-%e3%81%ae%e5%a0%b4%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;Linux の場合
&lt;/h2&gt;&lt;p&gt;Ubuntu 20.04 で確認しました。&lt;br&gt;
&lt;code&gt;libsecret&lt;/code&gt; をインストールして、&lt;code&gt;credential.helper&lt;/code&gt; に設定してやります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt-get install libsecret-1-0 libsecret-1-dev
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cd /usr/share/doc/git/contrib/credential/libsecret
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo make
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git config --global credential.helper /usr/share/doc/git/contrib/credential/libsecret/git-credential-libsecret
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで、一度ユーザー名とパスワードを入力したら、次回以降は入力不要になります。&lt;/p&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.katsubemakito.net/git/git-config-1st" target="_blank" rel="noopener"
 &gt;https://blog.katsubemakito.net/git/git-config-1st&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/Tebasaki314/items/da230ccc9ac891f4ba25" target="_blank" rel="noopener"
 &gt;https://qiita.com/Tebasaki314/items/da230ccc9ac891f4ba25&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>デザインを Materiapollo に変更しました</title><link>https://blog.ponkotools.com/posts/2021/06/01/materiapollo/</link><pubDate>Tue, 01 Jun 2021 00:00:00 +0900</pubDate><guid>https://blog.ponkotools.com/posts/2021/06/01/materiapollo/</guid><description>&lt;p&gt;当ブログのテーマを Materiapollo というテーマに変更しました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.cottpic.com/2018/04/materiapollo-v0-9-1-release.html" target="_blank" rel="noopener"
 &gt;https://www.cottpic.com/2018/04/materiapollo-v0-9-1-release.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;このテーマについて、カスタマイズして点についてまとめておきます。&lt;/p&gt;
&lt;h2 id="前準備"&gt;&lt;a href="#%e5%89%8d%e6%ba%96%e5%82%99" class="header-anchor"&gt;&lt;/a&gt;前準備
&lt;/h2&gt;&lt;p&gt;ソフトウェアエンジニアならばこういうテーマのカスタマイズも Git を使って管理しましょう。&lt;/p&gt;
&lt;h2 id="ウィジェットのアイコンを追加"&gt;&lt;a href="#%e3%82%a6%e3%82%a3%e3%82%b8%e3%82%a7%e3%83%83%e3%83%88%e3%81%ae%e3%82%a2%e3%82%a4%e3%82%b3%e3%83%b3%e3%82%92%e8%bf%bd%e5%8a%a0" class="header-anchor"&gt;&lt;/a&gt;ウィジェットのアイコンを追加
&lt;/h2&gt;&lt;p&gt;私はサイドバーに翻訳ウィジェットとかも表示しているので、それ用のアイコンを追加します。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;変更前&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.sidebar .widget.BlogArchive h2:before{content: &amp;#34;\e02f\00A0&amp;#34;;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.sidebar .widget.Label h2:before{content: &amp;#34;\e54e\00A0&amp;#34;;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.sidebar .widget.PopularPosts h2:before{content: &amp;#34;\e39f\00A0&amp;#34;;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;変更後&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;BlogSearch&lt;/code&gt; &lt;code&gt;Translate&lt;/code&gt; &lt;code&gt;ContactForm&lt;/code&gt; を追加しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.sidebar .widget.Translate h2:before{content: &amp;#34;\e8e2\00A0&amp;#34;;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.sidebar .widget.BlogSearch h2:before{content: &amp;#34;\e8b6\00A0&amp;#34;;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.sidebar .widget.BlogArchive h2:before{content: &amp;#34;\e02f\00A0&amp;#34;;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.sidebar .widget.Label h2:before{content: &amp;#34;\e54e\00A0&amp;#34;;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.sidebar .widget.PopularPosts h2:before{content: &amp;#34;\e39f\00A0&amp;#34;;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.sidebar .widget.ContactForm h2:before{content: &amp;#34;\e0be\00A0&amp;#34;;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;アイコンのコードは以下で調べられます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://fonts.google.com/icons" target="_blank" rel="noopener"
 &gt;https://fonts.google.com/icons&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ボタンのテキストが大文字にならないようにする"&gt;&lt;a href="#%e3%83%9c%e3%82%bf%e3%83%b3%e3%81%ae%e3%83%86%e3%82%ad%e3%82%b9%e3%83%88%e3%81%8c%e5%a4%a7%e6%96%87%e5%ad%97%e3%81%ab%e3%81%aa%e3%82%89%e3%81%aa%e3%81%84%e3%82%88%e3%81%86%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;ボタンのテキストが大文字にならないようにする
&lt;/h2&gt;&lt;p&gt;Material-UI ではボタンのテキストは全て大文字になってしまうのですが、これを解除します。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;READ MORE&lt;/code&gt; と ラベルの二カ所について以下のように修正します。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;変更前&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;a class=&amp;#39;btn col m12 right&amp;#39; expr:href=&amp;#39;data:post.url&amp;#39; style=&amp;#39;font-weight:600;&amp;#39;&amp;gt;Read more &amp;lt;i class=&amp;#39;material-icons medium chevron_r&amp;#39;&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;a class=&amp;#39;btn left post-per-page&amp;#39; expr:dir=&amp;#39;data:blog.languageDirection&amp;#39; expr:href=&amp;#39;data:label.url&amp;#39;&amp;gt;&amp;lt;data:label.name/&amp;gt;&amp;lt;b:if cond=&amp;#39;data:showFreqNumbers&amp;#39;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;変更後&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;a class=&amp;#39;btn col m12 right&amp;#39; expr:href=&amp;#39;data:post.url&amp;#39; style=&amp;#39;font-weight:600;&amp;#39;&amp;gt;Read more &amp;lt;i class=&amp;#39;material-icons medium chevron_r&amp;#39;&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;a class=&amp;#39;btn left post-per-page&amp;#39; style=&amp;#39;text-transform: none;&amp;#39; expr:dir=&amp;#39;data:blog.languageDirection&amp;#39; expr:href=&amp;#39;data:label.url&amp;#39;&amp;gt;&amp;lt;data:label.name/&amp;gt;&amp;lt;b:if cond=&amp;#39;data:showFreqNumbers&amp;#39;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="テーマの色を変更"&gt;&lt;a href="#%e3%83%86%e3%83%bc%e3%83%9e%e3%81%ae%e8%89%b2%e3%82%92%e5%a4%89%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;テーマの色を変更
&lt;/h2&gt;&lt;p&gt;ヘッダーの色は &lt;code&gt;#00acc1&lt;/code&gt;、ナビゲーションバーの色は &lt;code&gt;#00bcd4&lt;/code&gt; なので、これで検索したら修正箇所が見つかると思います。&lt;/p&gt;
&lt;h3 id="ヘッダーの色とテキストの配置"&gt;&lt;a href="#%e3%83%98%e3%83%83%e3%83%80%e3%83%bc%e3%81%ae%e8%89%b2%e3%81%a8%e3%83%86%e3%82%ad%e3%82%b9%e3%83%88%e3%81%ae%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;ヘッダーの色とテキストの配置
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;変更前&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;header{height:200px;background-color: #00acc1; overflow: hidden; color: #fff; text-align: center;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#headerleft{margin:0;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.headerleft h1{padding-top: 85px;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;変更後&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;header{background-color: #212121; overflow: hidden; color: #fff;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#headerleft{margin:0;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.headerleft h1{padding-top: 15px;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ナビゲーションバーの色"&gt;&lt;a href="#%e3%83%8a%e3%83%93%e3%82%b2%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3%e3%83%90%e3%83%bc%e3%81%ae%e8%89%b2" class="header-anchor"&gt;&lt;/a&gt;ナビゲーションバーの色
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;変更前&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nav{background-color: #00bcd4;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;変更後&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nav{background-color: #757575;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ドロップダウンリストの色"&gt;&lt;a href="#%e3%83%89%e3%83%ad%e3%83%83%e3%83%97%e3%83%80%e3%82%a6%e3%83%b3%e3%83%aa%e3%82%b9%e3%83%88%e3%81%ae%e8%89%b2" class="header-anchor"&gt;&lt;/a&gt;ドロップダウンリストの色
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;変更前&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nav.npin .dropdown-content li &amp;gt; a, .dropdown-content li &amp;gt; span {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; color: #00acc1;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;変更後&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nav.npin .dropdown-content li &amp;gt; a, .dropdown-content li &amp;gt; span {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; color: #212121;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="パンくずリストの色"&gt;&lt;a href="#%e3%83%91%e3%83%b3%e3%81%8f%e3%81%9a%e3%83%aa%e3%82%b9%e3%83%88%e3%81%ae%e8%89%b2" class="header-anchor"&gt;&lt;/a&gt;パンくずリストの色
&lt;/h3&gt;&lt;p&gt;リンクの色と合わせました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;変更前&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.breadcrumbs.card a {color: #00acc1;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;変更後&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.breadcrumbs.card a {color: #2196f3;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.breadcrumbs.card a:hover {color: #64b5f6;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="css-の追加"&gt;&lt;a href="#css-%e3%81%ae%e8%bf%bd%e5%8a%a0" class="header-anchor"&gt;&lt;/a&gt;CSS の追加
&lt;/h2&gt;&lt;p&gt;見出しをはじめ、全体的にコンテンツ内のデザインが素っ気なかったり、一部デザインが崩れていたりしたので、以下の CSS を追加しました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.marked&lt;/code&gt; は後述するマークダウンを適用している範囲を指定しています。&lt;/p&gt;
&lt;h3 id="見出し"&gt;&lt;a href="#%e8%a6%8b%e5%87%ba%e3%81%97" class="header-anchor"&gt;&lt;/a&gt;見出し
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked h1, .marked h2, .marked h3, .marked h4, .marked h5, .marked h6 {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; margin: 1em 0;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; font-weight: bold;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /* font-family: &amp;#39;Material Icons&amp;#39; */
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked h2 {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; padding: 0.4em;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; background: #eaf3ff;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; border-bottom: solid 3px #424242;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked h3 {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; padding-bottom: 0.4em;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; border-bottom: dotted 1px black;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="リスト"&gt;&lt;a href="#%e3%83%aa%e3%82%b9%e3%83%88" class="header-anchor"&gt;&lt;/a&gt;リスト
&lt;/h3&gt;&lt;p&gt;リストのマーカーは全てなしになっているのをデフォルト状態に戻しています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked ul &amp;gt; li {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; list-style-type: disc;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked ul &amp;gt; li &amp;gt; ul &amp;gt; li {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; list-style-type: circle;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked ul &amp;gt; li &amp;gt; ul &amp;gt; li &amp;gt; ul &amp;gt; li {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; list-style-type: square;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked ul {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; padding: 0 0 0 40px;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked li {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; padding: 0px;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; margin: 0 0 4px 0;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked ol {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; padding: 0 2.5em;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; margin: .5em 0;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; line-height: 1.4;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; list-style-type: decimal;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;デフォルト状態に戻したいだけなのに結構面倒です。&lt;br&gt;
以下のページが参考になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://standard.shiftbrain.com/blog/reset-and-restore-list-item-marker" target="_blank" rel="noopener"
 &gt;https://standard.shiftbrain.com/blog/reset-and-restore-list-item-marker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="コードブロック"&gt;&lt;a href="#%e3%82%b3%e3%83%bc%e3%83%89%e3%83%96%e3%83%ad%e3%83%83%e3%82%af" class="header-anchor"&gt;&lt;/a&gt;コードブロック
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked pre {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; margin: 0.5em 0 1.5em 0;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; border-radius:10px;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked p &amp;gt; code {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; padding: 0.1em 0.3em;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; color: palevioletred;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; background: ghostwhite;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; border: 1px;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; border: solid 1px darkgray;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; border-radius: 5px;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="テーブル"&gt;&lt;a href="#%e3%83%86%e3%83%bc%e3%83%96%e3%83%ab" class="header-anchor"&gt;&lt;/a&gt;テーブル
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked table{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; border-collapse: collapse;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; width: 100%;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked table tr{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; border-top: solid 1px #d0d0d0;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; border-bottom: solid 1px #d0d0d0;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cursor: pointer;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked table tr:hover{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; background-color: #eaf3ff;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked table th{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; padding: 15px;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; text-align: center;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; font-weight: bold;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.marked table td{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; padding: 15px;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="デフォルトの画像を追加"&gt;&lt;a href="#%e3%83%87%e3%83%95%e3%82%a9%e3%83%ab%e3%83%88%e3%81%ae%e7%94%bb%e5%83%8f%e3%82%92%e8%bf%bd%e5%8a%a0" class="header-anchor"&gt;&lt;/a&gt;デフォルトの画像を追加
&lt;/h2&gt;&lt;p&gt;記事中にある最初の画像がトップページに表示されますが、画像がない記事の場合は何も表示されず寂しいので、&lt;code&gt;NO IMAGE&lt;/code&gt; と表示されるようにします。&lt;br&gt;
ちなみに、画像ではなくマテリアルアイコンと文字列で作成しています。&lt;/p&gt;
&lt;h3 id="ホーム画面の-no-image"&gt;&lt;a href="#%e3%83%9b%e3%83%bc%e3%83%a0%e7%94%bb%e9%9d%a2%e3%81%ae-no-image" class="header-anchor"&gt;&lt;/a&gt;ホーム画面の NO IMAGE
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;変更前&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;b:if cond=&amp;#39;data:post.firstImageUrl&amp;#39;&amp;gt;&amp;lt;div class=&amp;#39;md-thumb col s12 m5 l5&amp;#39; style=&amp;#39;text-align: center;&amp;#39;&amp;gt;&amp;lt;a expr:href=&amp;#39;data:post.url&amp;#39;&amp;gt;&amp;lt;img expr:src=&amp;#39;data:post.firstImageUrl&amp;#39;/&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/b:if&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;変更後&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;div class=&amp;#39;md-thumb col s12 m5 l5&amp;#39; style=&amp;#39;text-align: center;&amp;#39;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;a expr:href=&amp;#39;data:post.url&amp;#39;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;b:if cond=&amp;#39;data:post.firstImageUrl&amp;#39;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;img expr:src=&amp;#39;data:post.firstImageUrl&amp;#39;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;b:else/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;div class=&amp;#34;noimage&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;i class=&amp;#34;material-icons large&amp;#34;&amp;gt;image&amp;lt;/i&amp;gt;&amp;lt;br/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;span&amp;gt;NO IMAGE&amp;lt;/span&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;/b:if&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;/a&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="人気記事の-no-image"&gt;&lt;a href="#%e4%ba%ba%e6%b0%97%e8%a8%98%e4%ba%8b%e3%81%ae-no-image" class="header-anchor"&gt;&lt;/a&gt;人気記事の NO IMAGE
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;変更前&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data:post.featuredImage.isResizable or data:post.thumbnail&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;item-thumbnail&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;position: absolute; top: 15px; left: 15px;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data:post.featuredImage.isResizable ? resizeImage(data:post.featuredImage, 72, &amp;amp;quot;1:1&amp;amp;quot;) : data:post.thumbnail&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;image&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="n"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;border&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data:image&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;width: 42px; height: 42px; padding-right: 0 !important; border-radius:4px;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;変更後&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;item-thumbnail&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;position: absolute; top: 15px; left: 15px;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data:post.featuredImage.isResizable or data:post.thumbnail&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data:post.featuredImage.isResizable ? resizeImage(data:post.featuredImage, 72, &amp;amp;quot;1:1&amp;amp;quot;) : data:post.thumbnail&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;image&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="n"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;border&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data:image&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;width: 42px; height: 42px; padding-right: 0 !important; border-radius:4px;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;noimage-small&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;material-icons small&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;br&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;NO&lt;/span&gt; &lt;span class="n"&gt;IMAGE&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="css"&gt;&lt;a href="#css" class="header-anchor"&gt;&lt;/a&gt;CSS
&lt;/h3&gt;&lt;p&gt;あとは上記に合わせて以下の CSS を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.noimage {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; color: #bdbdbd;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; font-size:30px;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; font-weight:bold;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.noimage-small {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; color: #bdbdbd;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; width: 42px;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; font-size:6px;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; font-weight:bold;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; text-align: center;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="その他"&gt;&lt;a href="#%e3%81%9d%e3%81%ae%e4%bb%96" class="header-anchor"&gt;&lt;/a&gt;その他
&lt;/h2&gt;&lt;p&gt;その他、以下のことをやっています。&lt;/p&gt;
&lt;h3 id="マークダウンで記事を書けるようにする"&gt;&lt;a href="#%e3%83%9e%e3%83%bc%e3%82%af%e3%83%80%e3%82%a6%e3%83%b3%e3%81%a7%e8%a8%98%e4%ba%8b%e3%82%92%e6%9b%b8%e3%81%91%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;マークダウンで記事を書けるようにする
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://kuttsun.blogspot.jp/2017/06/markdown-blogger.html" target="_blank" rel="noopener"
 &gt;こちらの記事&lt;/a&gt; を参照してください。&lt;/p&gt;
&lt;h3 id="シンタックスハイライトを設定する"&gt;&lt;a href="#%e3%82%b7%e3%83%b3%e3%82%bf%e3%83%83%e3%82%af%e3%82%b9%e3%83%8f%e3%82%a4%e3%83%a9%e3%82%a4%e3%83%88%e3%82%92%e8%a8%ad%e5%ae%9a%e3%81%99%e3%82%8b" class="header-anchor"&gt;&lt;/a&gt;シンタックスハイライトを設定する
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="http://kuttsun.blogspot.jp/2017/07/blogger-highlightjs.html" target="_blank" rel="noopener"
 &gt;こちらの記事&lt;/a&gt; を参照してください。&lt;/p&gt;
&lt;h3 id="投稿日時と更新日時の表示"&gt;&lt;a href="#%e6%8a%95%e7%a8%bf%e6%97%a5%e6%99%82%e3%81%a8%e6%9b%b4%e6%96%b0%e6%97%a5%e6%99%82%e3%81%ae%e8%a1%a8%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;投稿日時と更新日時の表示
&lt;/h3&gt;&lt;p&gt;以下のページを参考にさせていただきました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://wrxsti-fan.blogspot.com/2020/06/blogger-materiapollo.html" target="_blank" rel="noopener"
 &gt;https://wrxsti-fan.blogspot.com/2020/06/blogger-materiapollo.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="テーマ適用後にやったこと"&gt;&lt;a href="#%e3%83%86%e3%83%bc%e3%83%9e%e9%81%a9%e7%94%a8%e5%be%8c%e3%81%ab%e3%82%84%e3%81%a3%e3%81%9f%e3%81%93%e3%81%a8" class="header-anchor"&gt;&lt;/a&gt;テーマ適用後にやったこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ウィジェットの追加（翻訳など）&lt;/li&gt;
&lt;li&gt;フッターのウィジェットを削除&lt;/li&gt;
&lt;li&gt;人気記事のスニペットを非表示にした&lt;/li&gt;
&lt;li&gt;記事の作成者とコメント数を非表示にした&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="表示確認"&gt;&lt;a href="#%e8%a1%a8%e7%a4%ba%e7%a2%ba%e8%aa%8d" class="header-anchor"&gt;&lt;/a&gt;表示確認
&lt;/h2&gt;&lt;p&gt;以下、表示の確認です。&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id="見出し１"&gt;&lt;a href="#%e8%a6%8b%e5%87%ba%e3%81%97%ef%bc%91" class="header-anchor"&gt;&lt;/a&gt;見出し１
&lt;/h1&gt;&lt;h2 id="見出し２"&gt;&lt;a href="#%e8%a6%8b%e5%87%ba%e3%81%97%ef%bc%92" class="header-anchor"&gt;&lt;/a&gt;見出し２
&lt;/h2&gt;&lt;h3 id="見出し３"&gt;&lt;a href="#%e8%a6%8b%e5%87%ba%e3%81%97%ef%bc%93" class="header-anchor"&gt;&lt;/a&gt;見出し３
&lt;/h3&gt;&lt;h4 id="見出し４"&gt;&lt;a href="#%e8%a6%8b%e5%87%ba%e3%81%97%ef%bc%94" class="header-anchor"&gt;&lt;/a&gt;見出し４
&lt;/h4&gt;&lt;h5 id="見出し５"&gt;&lt;a href="#%e8%a6%8b%e5%87%ba%e3%81%97%ef%bc%95" class="header-anchor"&gt;&lt;/a&gt;見出し５
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;リスト
&lt;ul&gt;
&lt;li&gt;test&lt;/li&gt;
&lt;li&gt;test&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;インラインコード&lt;code&gt;code&lt;/code&gt;だよ&lt;/p&gt;
&lt;p&gt;&lt;font color="red"&gt;赤文字&lt;/font&gt;はHTMLで&lt;/p&gt;
&lt;p&gt;コードブロック&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;hoge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;hoge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;hoge&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;テーブル&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;header&lt;/th&gt;
 &lt;th&gt;header&lt;/th&gt;
 &lt;th&gt;header&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;hoge&lt;/td&gt;
 &lt;td&gt;hoge&lt;br&gt;テーブル内の改行は&lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt;で&lt;/td&gt;
 &lt;td&gt;hoge&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;hoge&lt;/td&gt;
 &lt;td&gt;hoge&lt;/td&gt;
 &lt;td&gt;hoge&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="参考-url"&gt;&lt;a href="#%e5%8f%82%e8%80%83-url" class="header-anchor"&gt;&lt;/a&gt;参考 URL
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://wrxsti-fan.blogspot.com/2020/06/blogger-materiapollo.html" target="_blank" rel="noopener"
 &gt;https://wrxsti-fan.blogspot.com/2020/06/blogger-materiapollo.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://saruwakakun.com/html-css/reference/h-design" target="_blank" rel="noopener"
 &gt;https://saruwakakun.com/html-css/reference/h-design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://standard.shiftbrain.com/blog/reset-and-restore-list-item-marker" target="_blank" rel="noopener"
 &gt;https://standard.shiftbrain.com/blog/reset-and-restore-list-item-marker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>