<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<title>m1sk9.dev</title>
	<subtitle>m1sk9&#x27;s portfolio and blog</subtitle>
	<link rel="self" type="application/atom+xml" href="https://m1sk9.dev/posts/feed.xml"/>
  <link rel="alternate" type="text/html" href="https://m1sk9.dev/posts/"/>
  
	<updated>2026-02-01T00:00:00+00:00</updated>
	
	<id>https://m1sk9.dev/posts/feed.xml</id>
	<entry xml:lang="en">
		<title>Paper (Spigot) の EventPriority とは何か</title>
		<published>2026-02-01T00:00:00+00:00</published>
		<updated>2026-02-01T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://m1sk9.dev/posts/about-paper-event-priority/"/>
		<id>https://m1sk9.dev/posts/about-paper-event-priority/</id>
    
		<content type="html" xml:base="https://m1sk9.dev/posts/about-paper-event-priority/">&lt;p&gt;EventPriority を適当に設定するな&lt;&#x2F;p&gt;
&lt;h2 id=&quot;eventpriority-toha&quot;&gt;EventPriority とは&lt;a class=&quot;zola-anchor&quot; href=&quot;#eventpriority-toha&quot; aria-label=&quot;Anchor link for: eventpriority-toha&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;EventPriority は，&lt;code&gt;@EventHandler&lt;&#x2F;code&gt; annotation の引数として指定できる列挙型で，イベントリスナーの実行順序を制御するための優先度システム．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;jd.papermc.io&#x2F;paper&#x2F;1.21.11&#x2F;org&#x2F;bukkit&#x2F;event&#x2F;EventHandler.html&quot;&gt;EventHandler (paper-api 1.21.11-R0.1-SNAPSHOT API)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;jd.papermc.io&#x2F;paper&#x2F;1.21.11&#x2F;org&#x2F;bukkit&#x2F;event&#x2F;EventPriority.html&quot;&gt;EventPriority (paper-api 1.21.11-R0.1-SNAPSHOT API)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;例えば複数のプラグインが同じイベント (例えば &lt;code&gt;PlayerJoinEvent&lt;&#x2F;code&gt; ) を捕捉しようとしている場合，どのプラグインが先に実行されるかを決めるのが EventPriority である．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;kotlin&quot; class=&quot;language-kotlin z-code&quot;&gt;&lt;code class=&quot;language-kotlin&quot; data-lang=&quot;kotlin&quot;&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;@EventHandler(priority &lt;span class=&quot;z-keyword z-operator z-assignment z-kotlin&quot;&gt;=&lt;&#x2F;span&gt; EventPriority&lt;span class=&quot;z-keyword z-operator z-dot z-kotlin&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-kotlin&quot;&gt;HIGHEST&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;&lt;span class=&quot;z-keyword z-other z-kotlin&quot;&gt;fun&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-kotlin&quot;&gt;onChat&lt;&#x2F;span&gt;(&lt;span class=&quot;z-variable z-parameter z-function z-kotlin&quot;&gt;event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-declaration z-kotlin&quot;&gt;:&lt;&#x2F;span&gt; AsyncChatEvent) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;  &lt;span class=&quot;z-keyword z-other z-kotlin&quot;&gt;val&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-variable z-kotlin&quot;&gt;player&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-kotlin&quot;&gt;=&lt;&#x2F;span&gt; event&lt;span class=&quot;z-keyword z-operator z-dot z-kotlin&quot;&gt;.&lt;&#x2F;span&gt;player
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;  &lt;span class=&quot;z-comment z-line z-double-slash z-kotlin&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-kotlin&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; ...
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;この優先度は以下のようになっている．&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;列挙型&lt;&#x2F;th&gt;&lt;th&gt;優先度&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;jd.papermc.io&#x2F;paper&#x2F;1.21.11&#x2F;org&#x2F;bukkit&#x2F;event&#x2F;EventPriority.html#HIGHEST&quot;&gt;&lt;code&gt;EventPriority.HIGHEST&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td&gt;最も高い&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;jd.papermc.io&#x2F;paper&#x2F;1.21.11&#x2F;org&#x2F;bukkit&#x2F;event&#x2F;EventPriority.html#HIGH&quot;&gt;&lt;code&gt;EventPriority.HIGH&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td&gt;高い&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;jd.papermc.io&#x2F;paper&#x2F;1.21.11&#x2F;org&#x2F;bukkit&#x2F;event&#x2F;EventPriority.html#NORMAL&quot;&gt;&lt;code&gt;EventPriority.NORMAL&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td&gt;通常 (デフォルト)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;4&lt;&#x2F;td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;jd.papermc.io&#x2F;paper&#x2F;1.21.11&#x2F;org&#x2F;bukkit&#x2F;event&#x2F;EventPriority.html#LOW&quot;&gt;&lt;code&gt;EventPriority.LOW&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td&gt;低&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;5&lt;&#x2F;td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;jd.papermc.io&#x2F;paper&#x2F;1.21.11&#x2F;org&#x2F;bukkit&#x2F;event&#x2F;EventPriority.html#LOWEST&quot;&gt;&lt;code&gt;EventPriority.LOWEST&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td&gt;最も低い&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;6&lt;&#x2F;td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;jd.papermc.io&#x2F;paper&#x2F;1.21.11&#x2F;org&#x2F;bukkit&#x2F;event&#x2F;EventPriority.html#MONITOR&quot;&gt;&lt;code&gt;EventPriority.MONITOR&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td&gt;監視用 (後述するイベントの結果を変更しない場合の優先度)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;shi-ifen-ke&quot;&gt;使い分け&lt;a class=&quot;zola-anchor&quot; href=&quot;#shi-ifen-ke&quot; aria-label=&quot;Anchor link for: shi-ifen-ke&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;EventPriority の使い分けは次のように考えると良い&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;HIGHEST&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;HIGH&lt;&#x2F;code&gt; : 他のプラグインよりも先に処理・キャンセルしたい場合に使用する．例えば，チャットフィルターや権限管理など，ゲームプレイに直接影響を与える処理に適している．&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;NORMAL&lt;&#x2F;code&gt; : 特に優先度を指定しない場合に使用する．多くのプラグインはこの優先度で十分である．&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;LOW&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;LOWEST&lt;&#x2F;code&gt; : 他のプラグインの処理が完了した後に実行したい場合に使用する．例えば，ログ記録や通知など，ゲームプレイに直接影響を与えない処理に適している．&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;適当に設定すると不具合の原因になるので，特にサーバのメインプラグインなどを開発している場合は注意が必要である．&lt;&#x2F;p&gt;
&lt;h2 id=&quot;monitor-toha&quot;&gt;MONITOR とは?&lt;a class=&quot;zola-anchor&quot; href=&quot;#monitor-toha&quot; aria-label=&quot;Anchor link for: monitor-toha&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;MONITOR&lt;&#x2F;code&gt; は，イベントの結果を変更しない場合に使用する優先度である．例えば，ログ記録や通知など，イベントの結果に影響を与えない処理 ( &lt;code&gt;read-only&lt;&#x2F;code&gt; )に適している．優先度的には &lt;code&gt;LOWEST&lt;&#x2F;code&gt; の次に実行される．なので，イベントの最終結果を監視したい場合に適しているのだ．&lt;&#x2F;p&gt;
&lt;p&gt;ログ管理プラグインとして有名な CoreProtect では &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PlayPro&#x2F;CoreProtect&#x2F;blob&#x2F;b0856b51a565ff6bb1266a98633437aae580c507&#x2F;src&#x2F;main&#x2F;java&#x2F;net&#x2F;coreprotect&#x2F;paper&#x2F;listener&#x2F;PaperChatListener.java#L15-L20&quot;&gt;&lt;code&gt;AsyncChatEvent&lt;&#x2F;code&gt; を &lt;code&gt;MONITOR&lt;&#x2F;code&gt; で捕捉し，チャット内容をログに記録している&lt;&#x2F;a&gt;．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;java&quot; class=&quot;language-java z-code&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-annotation z-java&quot;&gt;@&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-java&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-identifier z-java&quot;&gt;&lt;span class=&quot;z-variable z-annotation z-java&quot;&gt;EventHandler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-parameters z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-java&quot;&gt;priority&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;EventPriority&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-java&quot;&gt;MONITOR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;public&lt;&#x2F;span&gt; void &lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;onPlayerChat&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class z-java&quot;&gt;AsyncChatEvent&lt;&#x2F;span&gt; event&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;  &lt;span class=&quot;z-support z-class z-java&quot;&gt;String&lt;&#x2F;span&gt; message &lt;span class=&quot;z-meta z-assignment z-rhs z-java&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;PlainTextComponentSerializer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;plainText&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;serialize&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;event&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-conditional z-if z-java&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-parens z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;message&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;isEmpty&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-return z-java&quot;&gt;return&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;  &lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;  &lt;span class=&quot;z-comment z-line z-double-slash z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-java&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; ...
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;monitor-note-bie-nashi-yang&quot;&gt;&lt;code&gt;MONITOR&lt;&#x2F;code&gt; の特別な仕様&lt;a class=&quot;zola-anchor&quot; href=&quot;#monitor-note-bie-nashi-yang&quot; aria-label=&quot;Anchor link for: monitor-note-bie-nashi-yang&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;前述した通り， &lt;code&gt;MONITOR&lt;&#x2F;code&gt; は実行順序では最後になるが，単なる優先度ではなく，イベントの最終状態を観察するための専用列挙型として設計されている．&lt;&#x2F;p&gt;
&lt;h3 id=&quot;kiyanserubu-ke&quot;&gt;キャンセル不可&lt;a class=&quot;zola-anchor&quot; href=&quot;#kiyanserubu-ke&quot; aria-label=&quot;Anchor link for: kiyanserubu-ke&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;MONITOR&lt;&#x2F;code&gt; 以外の優先度 ( &lt;code&gt;HIGHEST&lt;&#x2F;code&gt; から &lt;code&gt;LOWEST&lt;&#x2F;code&gt; ) では，イベントをキャンセルすることが可能である．例えば， &lt;code&gt;PlayerJoinEvent&lt;&#x2F;code&gt; を &lt;code&gt;HIGHEST&lt;&#x2F;code&gt; で捕捉し，以下のようにイベントをキャンセルすることができる&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;java&quot; class=&quot;language-java z-code&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-annotation z-java&quot;&gt;@&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-java&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-identifier z-java&quot;&gt;&lt;span class=&quot;z-variable z-annotation z-java&quot;&gt;EventHandler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-parameters z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-java&quot;&gt;priority&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;EventPriority&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-java&quot;&gt;HIGHEST&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;public&lt;&#x2F;span&gt; void &lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;onPlayerJoin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class z-java&quot;&gt;PlayerJoinEvent&lt;&#x2F;span&gt; event&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    event&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;setCancelled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-java&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-comment z-line z-double-slash z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-java&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; プレイヤーの参加をキャンセル
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;しかし， &lt;code&gt;MONITOR&lt;&#x2F;code&gt; では，イベントをキャンセルすることはできない． &lt;code&gt;MONITOR&lt;&#x2F;code&gt; で捕捉されたイベントは，すでに他の優先度で処理されており，その結果を変更することは許されていない．以下のコードは無効である．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;java&quot; class=&quot;language-java z-code&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-annotation z-java&quot;&gt;@&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-java&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-identifier z-java&quot;&gt;&lt;span class=&quot;z-variable z-annotation z-java&quot;&gt;EventHandler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-parameters z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-java&quot;&gt;priority&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;EventPriority&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-java&quot;&gt;MONITOR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;public&lt;&#x2F;span&gt; void &lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;onPlayerJoin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class z-java&quot;&gt;PlayerJoinEvent&lt;&#x2F;span&gt; event&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-if z-java&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-parens z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;event&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;isCancelled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;        &lt;span class=&quot;z-comment z-line z-double-slash z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-java&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; 他のプラグインがキャンセルしたかどうか判定できる
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;        plugin&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;log&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-java&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Player join was cancelled&lt;span class=&quot;z-punctuation z-definition z-string z-end z-java&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-java&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; でもこのメソッドでは event.setCancelled(true) しても何も起こらない
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;akumadeibentonojian-shi-yong&quot;&gt;あくまでイベントの監視用&lt;a class=&quot;zola-anchor&quot; href=&quot;#akumadeibentonojian-shi-yong&quot; aria-label=&quot;Anchor link for: akumadeibentonojian-shi-yong&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;MONITOR&lt;&#x2F;code&gt; は，あくまでイベントの最終状態を監視するために使用されるべきであり，イベントの結果を変更するために使用されるべきではない．例えば，ログ記録や通知など，イベントの結果に影響を与えない処理に適している．&lt;&#x2F;p&gt;
&lt;p&gt;イベントキャンセルができない = 別のプラグインの妨害を無効化できるという考えなので，以下の使い方ができる．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;java&quot; class=&quot;language-java z-code&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-annotation z-java&quot;&gt;@&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-java&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-identifier z-java&quot;&gt;&lt;span class=&quot;z-variable z-annotation z-java&quot;&gt;EventHandler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-parameters z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-java&quot;&gt;priority&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;EventPriority&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-java&quot;&gt;MONITOR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;public&lt;&#x2F;span&gt; void &lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;onPlayerJoinMonitor&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class z-java&quot;&gt;PlayerJoinEvent&lt;&#x2F;span&gt; event&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-java&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; ログや統計情報の記録
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    logDatabase&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;recordJoin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;event&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;getPlayer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-java&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-java&quot;&gt;!&lt;&#x2F;span&gt;event&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;isCancelled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-java&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; メトリクスの更新
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    metrics&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;incrementPlayerJoinCount&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;event&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;isCancelled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;tickrate-henoying-xiang&quot;&gt;Tickrate への影響&lt;a class=&quot;zola-anchor&quot; href=&quot;#tickrate-henoying-xiang&quot; aria-label=&quot;Anchor link for: tickrate-henoying-xiang&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;MONITOR&lt;&#x2F;code&gt; は常に実行されるため，負荷のある処理 (例えばデータベースへのアクセスなど)を同期的に行うと，サーバの Tickrate に影響を及ぼしてしまう．そのため， &lt;code&gt;MONITOR&lt;&#x2F;code&gt; で重い処理を行う場合は，非同期に処理を行うか，別のスレッドで処理を行うことが推奨される．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;java&quot; class=&quot;language-java z-code&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-annotation z-java&quot;&gt;@&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-java&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-identifier z-java&quot;&gt;&lt;span class=&quot;z-variable z-annotation z-java&quot;&gt;EventHandler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-parameters z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-java&quot;&gt;priority&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;EventPriority&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-java&quot;&gt;MONITOR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;public&lt;&#x2F;span&gt; void &lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;onPlayerJoin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class z-java&quot;&gt;PlayerJoinEvent&lt;&#x2F;span&gt; event&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-support z-class z-java&quot;&gt;Bukkit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;getScheduler&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;runTaskAsynchronously&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;plugin&lt;span class=&quot;z-punctuation z-separator z-comma z-java&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function z-anonymous z-parameters z-java&quot;&gt;&lt;span class=&quot;z-meta z-function z-anonymous z-parameters z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-anonymous z-parameters z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function z-anonymous z-body z-java&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-anonymous z-java&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-meta z-function z-anonymous z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;        database&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;recordJoin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;event&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;getPlayer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-meta z-function z-anonymous z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;code&gt;PlayerJoinEvent&lt;&#x2F;code&gt; は実際にはキャンセル不可なイベント&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Litematica での設計図の作り方</title>
		<published>2026-01-26T00:00:00+00:00</published>
		<updated>2026-01-26T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://m1sk9.dev/posts/litematica-schematic-guide/"/>
		<id>https://m1sk9.dev/posts/litematica-schematic-guide/</id>
    
		<content type="html" xml:base="https://m1sk9.dev/posts/litematica-schematic-guide/">&lt;p&gt;Litematica の設計図についてのプレイヤー向けガイド的なもの&lt;&#x2F;p&gt;
&lt;h2 id=&quot;litematica-nodao-ru&quot;&gt;Litematica の導入&lt;a class=&quot;zola-anchor&quot; href=&quot;#litematica-nodao-ru&quot; aria-label=&quot;Anchor link for: litematica-nodao-ru&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Litematica は Mod なので各自で導入する必要があります．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;modrinth.com&#x2F;mod&#x2F;litematica&quot;&gt;Litematica - Minecraft Mod - Modrinth&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;対応バージョン: &lt;code&gt;1.12.x&lt;&#x2F;code&gt;, &lt;code&gt;1.13.2&lt;&#x2F;code&gt;, &lt;code&gt;1.14&lt;&#x2F;code&gt;, &lt;code&gt;1.14.2-1.14.4&lt;&#x2F;code&gt;, &lt;code&gt;1.15.x&lt;&#x2F;code&gt; ~ &lt;code&gt;1.19.x&lt;&#x2F;code&gt;, &lt;code&gt;1.20.1-1.20.4&lt;&#x2F;code&gt;, &lt;code&gt;1.20.6&lt;&#x2F;code&gt;, &lt;code&gt;1.21.x&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;対象 Mod Loader: Fabric, Forge, LiteLoader, Ornithe, Rift&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;1.21.x の対応は Fabric のみなので，手元に Fabric の環境を作っておく必要があるので注意が必要 (LiteLoader ならまだしも Ornithe, Rift なんて使ってる奴おるんか？？？)&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;ここでは Fabric 環境の構築方法や Mod の導入は省略します．ネットに死ぬほど情報が転がってるのでそれを読んでね．&lt;&#x2F;p&gt;
&lt;h2 id=&quot;she-ji-tu-toha&quot;&gt;設計図とは&lt;a class=&quot;zola-anchor&quot; href=&quot;#she-ji-tu-toha&quot; aria-label=&quot;Anchor link for: she-ji-tu-toha&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Litematica は &lt;code&gt;*.schematic&lt;&#x2F;code&gt; という形式の設計図ファイルを読み込み，建築物を透かしで表示して建築をサポートする Mod です．&lt;&#x2F;p&gt;
&lt;p&gt;今回のガイドはあくまで &lt;strong&gt;設計図を作ること&lt;&#x2F;strong&gt; なので， &lt;strong&gt;設計図を使うこと&lt;&#x2F;strong&gt; に関しては何も書きません．これもネットに死ぬほど情報が転がってるのでそれを読んでね．&lt;&#x2F;p&gt;
&lt;h2 id=&quot;she-ji-tu-woqu-ru&quot;&gt;設計図を取る&lt;a class=&quot;zola-anchor&quot; href=&quot;#she-ji-tu-woqu-ru&quot; aria-label=&quot;Anchor link for: she-ji-tu-woqu-ru&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;WorldEdit ではお馴染みの木の斧ですが， Litematica では木の棒を使う．&lt;&#x2F;p&gt;
&lt;p&gt;Litematica が導入された状態で木の棒を持つと左下に何か出てくると思う．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;litematica-schematic-guide&#x2F;.&#x2F;litematica-mode-info.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;見るべきところは一番下の Mode．画像では &lt;strong&gt;Area Selection&lt;&#x2F;strong&gt; になっています．これはエリア選択のモードってこと．&lt;&#x2F;p&gt;
&lt;p&gt;もし違うモードになっていたら Alt を押しながらマウスホイールでスクロールすると切り替えられる．&lt;&#x2F;p&gt;
&lt;h3 id=&quot;jian-zhu-wu-noeriawoxuan-ze-suru&quot;&gt;建築物のエリアを選択する&lt;a class=&quot;zola-anchor&quot; href=&quot;#jian-zhu-wu-noeriawoxuan-ze-suru&quot; aria-label=&quot;Anchor link for: jian-zhu-wu-noeriawoxuan-ze-suru&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;まずは &lt;strong&gt;Area Selection&lt;&#x2F;strong&gt; に切り替えて建築物のエリアを選択する．&lt;&#x2F;p&gt;
&lt;p&gt;WorldEdit で編集するのと同じように建築物の対角線上に始点・終点でエリアを囲む．このときも囲み方も WorldEdit と同じ．右クリック・左クリックでそれぞれ始点・終点を選択します．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;litematica-schematic-guide&#x2F;.&#x2F;litematica-area-selection.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;こんな感じ．&lt;&#x2F;p&gt;
&lt;h3 id=&quot;eriagaxuan-ze-sikirenaichang-he&quot;&gt;エリアが選択しきれない場合&lt;a class=&quot;zola-anchor&quot; href=&quot;#eriagaxuan-ze-sikirenaichang-he&quot; aria-label=&quot;Anchor link for: eriagaxuan-ze-sikirenaichang-he&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;建築物がデカすぎてエリア選択がうまくいかない場合は建築物をぐるっと含められるように始点・終点にブロックをおいて，空気ブロック (Air) もまとめて選択してしまうしかないです．&lt;&#x2F;p&gt;
&lt;p&gt;設計図としては 空気ブロック (Air) は無視されるので大丈夫．&lt;&#x2F;p&gt;
&lt;h3 id=&quot;she-ji-tu-wobao-cun-suru&quot;&gt;設計図を保存する&lt;a class=&quot;zola-anchor&quot; href=&quot;#she-ji-tu-wobao-cun-suru&quot; aria-label=&quot;Anchor link for: she-ji-tu-wobao-cun-suru&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;それでは設計図を保存しよう． Litematica のメニューを開く． (初期設定ではキーが多分バラバラなので，各自キー設定を見るように．)&lt;&#x2F;p&gt;
&lt;p&gt;いろんなのが出てくると思うが，まず &lt;strong&gt;Area Selection browser&lt;&#x2F;strong&gt; を選ぶ&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;litematica-schematic-guide&#x2F;.&#x2F;litematica-area-selection-menu.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;そしたら &lt;strong&gt;New selection&lt;&#x2F;strong&gt; からエリアを登録する．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;litematica-schematic-guide&#x2F;.&#x2F;litematica-new-area.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;登録できたら登録したエリアの &lt;strong&gt;Configure&lt;&#x2F;strong&gt; を選ぶと出てくる Area Editor にある &lt;strong&gt;Save Schematic&lt;&#x2F;strong&gt; を選ぶ．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;litematica-schematic-guide&#x2F;.&#x2F;litematica-save-schematic.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;適当な名前をつけて保存する．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;litematica-schematic-guide&#x2F;.&#x2F;litematica-area-editor-save-schematic.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;保存すると &lt;code&gt;.minecraft&#x2F;&lt;&#x2F;code&gt; のフォルダーにある &lt;code&gt;schematics&lt;&#x2F;code&gt; フォルダーに先ほど作成した &lt;code&gt;*.litematic&lt;&#x2F;code&gt; ファイルがある．これが設計図になる．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;litematica-schematic-guide&#x2F;.&#x2F;windows-explorer.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;litematic-to-schematics-nowei-i&quot;&gt;*.litematic と *.schematics の違い&lt;a class=&quot;zola-anchor&quot; href=&quot;#litematic-to-schematics-nowei-i&quot; aria-label=&quot;Anchor link for: litematic-to-schematics-nowei-i&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;*.litematic&lt;&#x2F;code&gt; は Litematica 専用の設計図ファイルで，ブロック配置だけでなく，バージョン情報・材料リスト用データ・検証用データなど，Litematica機能向けのメタ情報が多く入っている．&lt;&#x2F;p&gt;
&lt;p&gt;それに対して &lt;code&gt;*.schematics&lt;&#x2F;code&gt; (&lt;code&gt;*.schematic&lt;&#x2F;code&gt;) は Litematica が流行る前に存在していた設計図 Mod である MCEdit や Schematica などで使われていた「古い共通フォーマット」で， Litematica でも読み込めるが，材料リストなどのデータが使えないという欠点がある．&lt;&#x2F;p&gt;
&lt;p&gt;基本は &lt;code&gt;*.litematic&lt;&#x2F;code&gt; で OK.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;一部の Minecraft オタクしか知らんやろ&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Git の cherry-pick について考える</title>
		<published>2026-01-22T00:00:00+00:00</published>
		<updated>2026-01-22T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://m1sk9.dev/posts/git-cherrypick/"/>
		<id>https://m1sk9.dev/posts/git-cherrypick/</id>
    
		<content type="html" xml:base="https://m1sk9.dev/posts/git-cherrypick/">&lt;p&gt;Git には既存のコミットの内容を適用する cherry-pick という機能がある．
今日はこの機能について考えたいと思う．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; cherry-pick &lt;span class=&quot;z-keyword z-control z-regexp z-set z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;-&lt;span class=&quot;z-keyword z-operator z-word z-shell&quot;&gt;-&lt;&#x2F;span&gt;edit&lt;span class=&quot;z-keyword z-control z-regexp z-set z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-regexp z-set z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;-n&lt;span class=&quot;z-keyword z-control z-regexp z-set z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-regexp z-set z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;-m &amp;lt;parent&lt;span class=&quot;z-keyword z-operator z-word z-shell&quot;&gt;-&lt;&#x2F;span&gt;number&amp;gt;&lt;span class=&quot;z-keyword z-control z-regexp z-set z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-regexp z-set z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;-s&lt;span class=&quot;z-keyword z-control z-regexp z-set z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-regexp z-set z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;-x&lt;span class=&quot;z-keyword z-control z-regexp z-set z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-regexp z-set z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;-&lt;span class=&quot;z-keyword z-operator z-word z-shell&quot;&gt;-&lt;&#x2F;span&gt;ff&lt;span class=&quot;z-keyword z-control z-regexp z-set z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;		  &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;[-S[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;keyid&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;]] &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;commit&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;…​&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; cherry-pick (--continue&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-pipe z-shell&quot;&gt;|&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;--skip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-pipe z-shell&quot;&gt;|&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;--abort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-pipe z-shell&quot;&gt;|&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;--quit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-cherry-pick&quot;&gt;Git - git-cherry-pick Documentation&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;nande-cherry-pick-tuteiuno&quot;&gt;なんで cherry-pick っていうの?&lt;a class=&quot;zola-anchor&quot; href=&quot;#nande-cherry-pick-tuteiuno&quot; aria-label=&quot;Anchor link for: nande-cherry-pick-tuteiuno&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;元は英語の慣用句 「cherry-picking」 から来ているらしい．
慣用句としては「良いものだけを選んで取る」「いいとこ取りをする」という意味がある．&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;the action or practice of choosing and taking only the most beneficial or profitable items, opportunities, etc., from what is available.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;it is an exaggeration based on the cherry-picking of facts&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;shi-ifang&quot;&gt;使い方&lt;a class=&quot;zola-anchor&quot; href=&quot;#shi-ifang&quot; aria-label=&quot;Anchor link for: shi-ifang&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;cherry-pick は，特定の commit を現在地点の branch へ適用するコマンドで，基本は引数に適用したい commit hash を選ぶだけ．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; cherry-pick &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;commit-hash&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;commit hash は &lt;code&gt;git log&lt;&#x2F;code&gt; で確認するのもいいし， GitHub からでも確認できる．&lt;&#x2F;p&gt;
&lt;p&gt;(GUI 主義者はぜひ GitHub からコピーしよう．)&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;commit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; c0fd6e4c28967a66969cade0a212d7cee6d2728c&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Author:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; Sho Sakuma &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;me@m1sk9.dev&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; Date: Tue Jan 20 20:37:02 2026 +0900 test: Add Kana Conversion Test&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;git-cherrypick&#x2F;.&#x2F;github-commit.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;これが便利なシチュエーションとして&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;他の branch から特定の修正だけを取り込みたい&lt;&#x2F;li&gt;
&lt;li&gt;間違った branch に commit してしまった変更を正しい branch に移したいとき&lt;&#x2F;li&gt;
&lt;li&gt;Release branch に特定の hotfix だけを適用したいとき
&lt;ul&gt;
&lt;li&gt;(でもこれは worktree で良くないか... というのは置いといて) &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;で役立つ．私もよく使う．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; 複数のコミットを順番に適用&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; cherry-pick &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;commit1&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;commit2&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;commit3&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; コミット範囲を指定（commit1は含まれない）&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; cherry-pick &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;commit1&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;..&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;commit2&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; コミット範囲を指定（commit1も含む）&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; cherry-pick &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;commit1&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;^..&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;commit2&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; コミットせずにステージングエリアに追加&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; cherry-pick&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;no-commit&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;commit-hash&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; コミットメッセージを編集&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; cherry-pick&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;edit&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;commit-hash&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;ただ，この cherry-pick を行うと新しい commit hash として扱われることから， conflict が発生する．これらを解決しないと merge が出来ないので注意が必要．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; コンフリクトを解決後&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; cherry-pick&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; cherry-pick を中止&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; cherry-pick&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;abort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; 現在の状態をスキップして次へ&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; cherry-pick&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;skip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;worktree って分かりづらい機能だよなって思ってる&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>私の開発環境 2026</title>
		<published>2026-01-14T00:00:00+00:00</published>
		<updated>2026-01-14T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://m1sk9.dev/posts/development-2026/"/>
		<id>https://m1sk9.dev/posts/development-2026/</id>
    
		<content type="html" xml:base="https://m1sk9.dev/posts/development-2026/">&lt;p&gt;2026年最初の記事です．&lt;&#x2F;p&gt;
&lt;p&gt;あけましておめでとうございます．本年もどうぞよろしくお願いします．&lt;&#x2F;p&gt;
&lt;p&gt;AI のおかげでかなり変わりました．ということで現状の私の開発環境を紹介します．&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ai-nituitenokao-efang&quot;&gt;AI についての考え方&lt;a class=&quot;zola-anchor&quot; href=&quot;#ai-nituitenokao-efang&quot; aria-label=&quot;Anchor link for: ai-nituitenokao-efang&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;AI 関連の記事に汚染されてしまった Zenn を嘆いていた私も今 Claude と Claude Code を使いまくってます．&lt;&#x2F;p&gt;
&lt;p&gt;私はコードを全て AI に書かせて人間によるレビューを行わない Vibe Coding というスタイルに対しては懐疑的です． Claude Code にコード生成するのはあくまで補助的な役割で，コードの大枠は自分で書きます．&lt;&#x2F;p&gt;
&lt;p&gt;AI を使って確かに効率化はできますし，私もそれはわかっているのである部分をより良い書き方はないかの質問や，初見のプログラミング言語を Rust や Kotlin など慣れ親しんだ言語で書き換えて理解する みたいなこともします．&lt;&#x2F;p&gt;
&lt;p&gt;Vide Coding の全てを否定するわけではありません．私も簡単なコードや使い捨てプログラムなどは Claude に書いてもらって使います．ただ人が使うコードなど私だけが使うプログラムではない場合は Claude に任せてはいけないと考えています．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;development-2026&#x2F;.&#x2F;claude-code.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;qian-ti&quot;&gt;前提&lt;a class=&quot;zola-anchor&quot; href=&quot;#qian-ti&quot; aria-label=&quot;Anchor link for: qian-ti&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;MacBook Air M2 (2022)
&lt;ul&gt;
&lt;li&gt;メモリ 16GB&lt;&#x2F;li&gt;
&lt;li&gt;ストレージ 512GB&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;MacBook Pro が欲しい〜〜〜〜 &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;www.itmedia.co.jp&#x2F;aiplus&#x2F;articles&#x2F;2512&#x2F;15&#x2F;news038.html&quot;&gt;メモリ高騰を引き起こした OpenAI のアイツを俺は許しません&lt;&#x2F;a&gt;．&lt;&#x2F;p&gt;
&lt;p&gt;また，私の設定は GitHub で公開しています．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;m1sk9&#x2F;dotfiles&quot;&gt;m1sk9&#x2F;dotfiles: My dotfiles.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;taminaru&quot;&gt;ターミナル&lt;a class=&quot;zola-anchor&quot; href=&quot;#taminaru&quot; aria-label=&quot;Anchor link for: taminaru&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;ターミナルは引き続き Ghostty を使用しています．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;m1sk9&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;dot_config&#x2F;ghostty&#x2F;config&quot;&gt;設定: dot_config&#x2F;ghostty&#x2F;config&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;development-2026&#x2F;github.com&#x2F;ghostty-org&#x2F;ghostty&quot;&gt;ghostty-org&#x2F;ghostty: 👻 Ghostty is a fast, feature-rich, and cross-platform terminal emulator that uses platform-native UI and GPU acceleration.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Lua を使って設定ファイルを書ける WezTerm を検討していたこともありましたが，盆栽が続いたことがない (NeoVim など) ので諦めました．&lt;&#x2F;p&gt;
&lt;p&gt;Ghostty はかなり気に入っています．2025年の中で &lt;em&gt;Best Teminal&lt;&#x2F;em&gt; でした．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;development-2026&#x2F;.&#x2F;ghostty.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;edeita&quot;&gt;エディタ&lt;a class=&quot;zola-anchor&quot; href=&quot;#edeita&quot; aria-label=&quot;Anchor link for: edeita&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;エディタは VSCode をやめて Zed を使用しています．今この記事も Zed で書いています．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;m1sk9&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;dot_config&#x2F;zed&#x2F;private_settings.json&quot;&gt;設定: dot_config&#x2F;zed&#x2F;private_settings.json&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;development-2026&#x2F;github.com&#x2F;zed-industries&#x2F;zed&quot;&gt;zed-industries&#x2F;zed: Code at the speed of thought – Zed is a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;VSCode は Electron を使っているからかかなり起動がもっさりしている印象で，使っていてかなりストレスフルだった印象があるとやっぱり速度を求めている私はしんどい...&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;zed.dev&#x2F;blog&#x2F;dev-containers&quot;&gt;DevContainer への対応は始まったばかり&lt;&#x2F;a&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; なのかかなり甘いので，完全移行にはなっていませんが，今年は Zed を使うことが多くなりそう． Claude Code にビルドイン対応しているのも大きいので．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;development-2026&#x2F;.&#x2F;zed.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;git-guan-lian&quot;&gt;Git 関連&lt;a class=&quot;zola-anchor&quot; href=&quot;#git-guan-lian&quot; aria-label=&quot;Anchor link for: git-guan-lian&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;こちらは引き続き lazygit を使用しています．TUI での操作が一番楽になってしまった．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;m1sk9&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;dot_config&#x2F;jesseduffield&#x2F;lazygit&#x2F;config.yml&quot;&gt;設定: dot_config&#x2F;jesseduffield&#x2F;lazygit&#x2F;config.yml&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jesseduffield&#x2F;lazygit&quot;&gt;jesseduffield&#x2F;lazygit: simple terminal UI for git commands&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;m1sk9&#x2F;dotfiles&#x2F;blob&#x2F;0fa2c4901976bc9796eaead53ba4c05fac5b0dbd&#x2F;dot_config&#x2F;jesseduffield&#x2F;lazygit&#x2F;config.yml#L17-L32&quot;&gt;カスタムコマンド&lt;&#x2F;a&gt; を定義して，全ファイルを stash したり，commit を打ち消すコマンドを追加したりもしています．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;customCommands&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;u&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;context&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;files&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;description&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Stash unstaged files&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;git stash save --include-untracked&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;r&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;context&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;status&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;description&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Add remote url&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;git remote add origin &amp;quot;{{index .PromptResponses 0}}&amp;quot; &lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;prompts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;input&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;title&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;remote url&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;lt;c-c&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;context&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;commits&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;description&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Cancel commit&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;git reset --soft HEAD^&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;development-2026&#x2F;.&#x2F;lazygit.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;kai-fa-huan-jing&quot;&gt;開発環境&lt;a class=&quot;zola-anchor&quot; href=&quot;#kai-fa-huan-jing&quot; aria-label=&quot;Anchor link for: kai-fa-huan-jing&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;開発環境は次のように管理しています&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Rust: rustup を使って直接管理&lt;&#x2F;li&gt;
&lt;li&gt;それ以外: &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jdx&#x2F;mise&quot;&gt;mise&lt;&#x2F;a&gt; を使って管理&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;mise で管理している理由はまあ &lt;a href=&quot;..&#x2F;contain-nodejs-in-devcontainer&quot;&gt;Node.js と npm エコシステムの1件&lt;&#x2F;a&gt; があったのもありますが，複数バージョンを管理する上で一番使いやすかったというのがあります．&lt;&#x2F;p&gt;
&lt;p&gt;asdf など世に出回ってる管理ツールを使ってきたが，mise に勝る点がなかったです．それぐらい優秀．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;development-2026&#x2F;.&#x2F;mise.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;lefthook や terraform, tflint, trivy などもインストールできるのだいぶ強い．&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;今見ると1月7日公開だった... そりゃ甘いね&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>直近のMinecraft界隈の話とサーバーを開けるのがどれだけ大変か</title>
		<published>2025-12-17T00:00:00+00:00</published>
		<updated>2025-12-17T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://m1sk9.dev/posts/minecraft-server-ops-nightmare/"/>
		<id>https://m1sk9.dev/posts/minecraft-server-ops-nightmare/</id>
    
		<content type="html" xml:base="https://m1sk9.dev/posts/minecraft-server-ops-nightmare/">&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;blog.yurisi.space&#x2F;archives&#x2F;10&quot;&gt;俺の友達が Minecraft サーバについてのブログを出していた&lt;&#x2F;a&gt; ので，アンサーというかまあ直近の話でもしとこうかなと．&lt;&#x2F;p&gt;
&lt;p&gt;大前提として俺は某鯖の運営を7月くらいに退いていて，これからの話は &lt;strong&gt;個人的な見解&lt;&#x2F;strong&gt; として見てください．もうあの鯖とは関係持ってないからね．&lt;&#x2F;p&gt;
&lt;h2 id=&quot;zui-jin-no-minecraft-sabanituite&quot;&gt;最近の Minecraft サーバについて&lt;a class=&quot;zola-anchor&quot; href=&quot;#zui-jin-no-minecraft-sabanituite&quot; aria-label=&quot;Anchor link for: zui-jin-no-minecraft-sabanituite&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;さっき出したブログでも触れられていたように，最近はMinecraftのコミュニティがあまり活発ではないのは事実．&lt;&#x2F;p&gt;
&lt;p&gt;サーバリストも昔は &lt;strong&gt;Japan Minecraft Servers&lt;&#x2F;strong&gt; と &lt;strong&gt;Monocraft&lt;&#x2F;strong&gt; という2つのサービスで大いに賑わっていたんだけど，後者は半年前くらいにサービスが止まったまま動かずに放置されている．&lt;&#x2F;p&gt;
&lt;p&gt;自分が &lt;strong&gt;サーバリストはすぐに死ぬもの&lt;&#x2F;strong&gt; って言ってるのもこういうことなんだけど，基本的に Minecraft コミュニティは &lt;strong&gt;個人の力&lt;&#x2F;strong&gt; で賑わっているものが多いから資金繰りに失敗したり，モチベーションの維持に失敗してサービスを閉じざる負えなくなってしまう．&lt;&#x2F;p&gt;
&lt;h2 id=&quot;yun-ying-gairunohadang-tariqian-ziyanai&quot;&gt;運営がいるのは当たり前じゃない&lt;a class=&quot;zola-anchor&quot; href=&quot;#yun-ying-gairunohadang-tariqian-ziyanai&quot; aria-label=&quot;Anchor link for: yun-ying-gairunohadang-tariqian-ziyanai&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Minecraft サーバでお金を稼ぐことは難しいから，基本的に Minecraft サーバの運営は全員無休のボランティアとして働いている．お金をもらっているわけではない．&lt;&#x2F;p&gt;
&lt;p&gt;そしてその運営も各サーバのオーナーが信頼をおける人間じゃないといけないから，すぐに&lt;strong&gt;増員したりもできない&lt;&#x2F;strong&gt;．だって誰もお金がもらえないのに無休で働いてほしいって言われて働くわけないでしょ? ね?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;minecraft-nozi-jin-zao-rinoda-bian-sa&quot;&gt;Minecraft の資金繰りの大変さ&lt;a class=&quot;zola-anchor&quot; href=&quot;#minecraft-nozi-jin-zao-rinoda-bian-sa&quot; aria-label=&quot;Anchor link for: minecraft-nozi-jin-zao-rinoda-bian-sa&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;ブログでも触れられていたお金の話をしたいと思う．&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;皆様に満足していただけるものにするには費用がかかりすぎた&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Minecraft のマルチサーバは本当にお金がかかります．マジで．&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;先ほどの記事では大雑把だったが，実際に今から立てようとすると，&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;www.vultr.com&#x2F;pricing&#x2F;#cloud-compute&quot;&gt;サーバ代: 12000円&lt;&#x2F;a&gt;，&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;tcpshield.com&#x2F;plans&quot;&gt;DDoS (サーバへの攻撃) への防衛: 4000円&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;その他もろもろで月額3万円が必要になる．それを学生などが持つと考えるとどうだろうか．バイト代の半分も無くなってしまう．参考程度に某鯖のお財布事情でも見てみればいい．自宅サーバでもちゃんとかかる．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;www.seichi.network&#x2F;post&#x2F;seichi-click-network%E3%81%AE%E3%81%8A%E8%B2%A1%E5%B8%83%E4%BA%8B%E6%83%85%E3%81%A8%E3%81%8B&quot;&gt;seichi click networkのお財布事情とか&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;実際運営している間もプレイヤーから「じゃあソシャゲみたいに課金要素追加すればいいじゃん」とか「法人化すればいいじゃん」とかめちゃくちゃ言われたけど &lt;strong&gt;出来ない&lt;&#x2F;strong&gt;．&lt;&#x2F;p&gt;
&lt;p&gt;ここで立ちはだかってくるのが Minecraft EULA というものの存在．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;www.minecraft.net&#x2F;en-us&#x2F;eula&quot;&gt;Minecraft End(er)-User License Agreement (“EULA”)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;minecraft-server-ops-nightmare&#x2F;.&#x2F;minecraft-eula.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align: center; font-size: 0.80em; color: #888; margin-top: 8px;&quot;&gt;
    はい今嫌な顔したそこの Minecraft 関係者
&lt;&#x2F;div&gt;
&lt;p&gt;まあようは利用規約みたいなものなんだけど，この EULA の中には (&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;www.minecraft.net&#x2F;en-us&#x2F;usage-guidelines&quot;&gt;Minecraft Usage Guidelines&lt;&#x2F;a&gt;) Minecraft を使って商標活動(平たく言えば金稼ぎ)をする上でのガイドラインが書いてある．&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Selling entitlements that affect gameplay provided they don’t ruin other players’ experience or give a competitive advantage in the game&lt;&#x2F;p&gt;
&lt;p&gt;(ゲームプレイに影響を与える特典を販売してよいが、他プレイヤーの体験を台無しにしたり、ゲーム内で競争上の優位性を与えてはならない)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;このようにソシャゲのような課金要素を明確に禁止と言われている以上 &lt;strong&gt;マルチサーバで資金を確保するのが難しい&lt;&#x2F;strong&gt; のである．(過去に俺にそういう文句を言ってきた人はこれを見て学んでください)&lt;&#x2F;p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https:&#x2F;&#x2F;www.youtube-nocookie.com&#x2F;embed&#x2F;vba04dugWms?si=Op3HghmqGDaLFZFv&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;h2 id=&quot;soredemo-an-ga-sabawokai-koutosuruli-you-yun-ying-huo-dong-wositeitali-you&quot;&gt;それでも (俺が) サーバを開こうとする理由 &#x2F; 運営活動をしていた理由&lt;a class=&quot;zola-anchor&quot; href=&quot;#soredemo-an-ga-sabawokai-koutosuruli-you-yun-ying-huo-dong-wositeitali-you&quot; aria-label=&quot;Anchor link for: soredemo-an-ga-sabawokai-koutosuruli-you-yun-ying-huo-dong-wositeitali-you&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;楽しいから&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;今自分がエンジニアとして会社で働いているのも，大学生として情報工学(平たく言えばプログラミング)を学んでいるのも元はと言えば Minecraft のおかげなので，それなりに感謝している．&lt;&#x2F;p&gt;
&lt;p&gt;Minecraft は無限大なのでなんでもできる．だからこそ資金繰りが大変でもめちゃくちゃ文句言われてもなんとかモチベーションを保てている．(何回かやめようと思ったり，フレンドに愚痴ったりしたけど)&lt;&#x2F;p&gt;
&lt;p&gt;だから今もどっかのタイミングでサーバを開こうとしてるし，運営活動をしていたのが理由の一つです．&lt;&#x2F;p&gt;
&lt;p&gt;これが今言いたいことの全て! 以上です．&lt;&#x2F;p&gt;
&lt;h2 id=&quot;omake-xin-yu-zhou-qing-spaceserveruniverse-nokoto&quot;&gt;おまけ: 新宇宙鯖 (SpaceServerUniverse) のこと&lt;a class=&quot;zola-anchor&quot; href=&quot;#omake-xin-yu-zhou-qing-spaceserveruniverse-nokoto&quot; aria-label=&quot;Anchor link for: omake-xin-yu-zhou-qing-spaceserveruniverse-nokoto&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;開発停止理由が公の場 (ブログで触れられていた) に出たので，ちょっと詳しい解説を加えようと思います．ここからはちょっと深い話になるので読みたい人だけ読んでください．&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;オリジナルのワールド生成が出来ない…&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;技術的には可能だとは思うのですが、調べてもそのような文献が余り出てこないだけでなくコードを読むとMinecraftのワールドのアルゴリズムを理解していないと出来なさそうでした。厳しい。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;リソースパック，データパックへの知見がある人は多分 &lt;strong&gt;簡単じゃん&lt;&#x2F;strong&gt; と思うだろうが， Bukkit (Spigot&#x2F;Paper) だとちょっと話が変わってくる．&lt;&#x2F;p&gt;
&lt;p&gt;2021年6月8日&#x2F;11月30日にリリースされた Minecraft 1.17, 1.18 (洞窟と崖) ではワールド生成のアルゴリズムに変更が加わったので，過去の人間が開発していたカスタムワールド系のプラグインは全滅してしまった．現状の最新バージョン 1.21.10 でのアルゴリズムに関しては解明できていない．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;ja.minecraft.wiki&#x2F;w&#x2F;Java_Edition_1.18#%E3%83%AF%E3%83%BC%E3%83%AB%E3%83%89%E7%94%9F%E6%88%90&quot;&gt;Java Edition 1.18 # 洞窟&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;洞窟&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;完全に作り変えられた。&lt;&#x2F;li&gt;
&lt;li&gt;Y=-59まで伸びるようになった&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;開発中に原因が突き止めればよかった．申し訳ないと思っているのでどっかのタイミングでこの原因を解明したいと思う．ちょっと待っててね．&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Node.js の環境を DevContainer に封じ込めよう</title>
		<published>2025-12-10T00:00:00+00:00</published>
		<updated>2025-12-10T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://m1sk9.dev/posts/contain-nodejs-in-devcontainer/"/>
		<id>https://m1sk9.dev/posts/contain-nodejs-in-devcontainer/</id>
    
		<content type="html" xml:base="https://m1sk9.dev/posts/contain-nodejs-in-devcontainer/">&lt;blockquote&gt;
&lt;p&gt;この記事は &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;adventar.org&#x2F;calendars&#x2F;11516&quot;&gt;mstdn.maud.io Advent Calendar 2025&lt;&#x2F;a&gt; 10日目の記事です．&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;11月24日 &lt;code&gt;postman&lt;&#x2F;code&gt; や &lt;code&gt;zapier&lt;&#x2F;code&gt; など 500 以上のパッケージがサプライチェーン攻撃を受けていたことが報告されました．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;socket.dev&#x2F;blog&#x2F;shai-hulud-strikes-again-v2&quot;&gt;Shai Hulud Strikes Again (v2) - Socket&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-media-max-width=&quot;560&quot;&gt;&lt;p lang=&quot;ja&quot; dir=&quot;ltr&quot;&gt;postmanやzapierが攻撃されていた。bunをインストールして悪意のあるスクリプトが動くっぽい &#x2F; Shai Hulud Strikes Again (v2) - Socket &lt;a href=&quot;https:&#x2F;&#x2F;t.co&#x2F;q0xsBHYyhh&quot;&gt;https:&#x2F;&#x2F;t.co&#x2F;q0xsBHYyhh&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;&amp;mdash; hiroppy (@about_hiroppy) &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;about_hiroppy&#x2F;status&#x2F;1992933867700007274?ref_src=twsrc%5Etfw&quot;&gt;November 24, 2025&lt;&#x2F;a&gt;&lt;&#x2F;blockquote&gt; &lt;script async src=&quot;https:&#x2F;&#x2F;platform.twitter.com&#x2F;widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;&#x2F;script&gt;
&lt;p&gt;この Shai Hulud というサプライチェーン攻撃は実は9月にも同様に発生しており， &lt;code&gt;@ctrl&#x2F;tinycolor&lt;&#x2F;code&gt; パッケージなども同様の手口によって攻撃を受けました．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;gigazine.net&#x2F;news&#x2F;20250917-shai-hulud-npm-packages&#x2F;&quot;&gt;毎週200万回以上ダウンロードされる人気の@ctrl&#x2F;tinycolorパッケージが高度なサプライチェーン攻撃「Shai-Hulud」によって40以上のNPMパッケージとともに侵害を受けていると発覚 - GIGAZINE&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;みなさん驚きなんと今年2回目！w&lt;&#x2F;p&gt;
&lt;h1 id=&quot;nantokanarannoka&quot;&gt;なんとかならんのか?&lt;a class=&quot;zola-anchor&quot; href=&quot;#nantokanarannoka&quot; aria-label=&quot;Anchor link for: nantokanarannoka&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h1&gt;
&lt;p&gt;Node.js のエコシステムは非常に大きいもので，全世界に数百万のパッケージが存在している上に，それらのパッケージは全世界のプロダクトに利用されています．&lt;&#x2F;p&gt;
&lt;p&gt;私個人としては Node.js のエコシステムに関しては &lt;strong&gt;呆れ&lt;&#x2F;strong&gt; と &lt;strong&gt;諦念&lt;&#x2F;strong&gt; の感情が強く，この脆弱なシステムはもはやどうしようもないと思っています．&lt;&#x2F;p&gt;
&lt;p&gt;(というかどうにかなってたら恐らく Deno は産まれてないし&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;，こんなサプライチェーン攻撃が頻繁には行われないでしょう)&lt;&#x2F;p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;embed&#x2F;swXWUfufu2w?si=fWOG9rZxCL4o18gB&amp;amp;start=61&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;h1 id=&quot;devcontainer-nosu-me&quot;&gt;DevContainer のすゝめ&lt;a class=&quot;zola-anchor&quot; href=&quot;#devcontainer-nosu-me&quot; aria-label=&quot;Anchor link for: devcontainer-nosu-me&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h1&gt;
&lt;p&gt;エコシステムが脆弱なら，ローカルを最後の砦として守るしかありません．&lt;&#x2F;p&gt;
&lt;p&gt;私が最近使っているのは DevContainer です．つい最近も PHP をローカルから追い出して気持ちよくなってました&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;．&lt;&#x2F;p&gt;
&lt;blockquote class=&quot;mastodon-embed&quot; data-embed-url=&quot;https:&#x2F;&#x2F;mstdn.maud.io&#x2F;@m1sk9&#x2F;115613453651083916&#x2F;embed&quot; style=&quot;background: #FCF8FF; border-radius: 8px; border: 1px solid #C9C4DA; margin: 0; max-width: 540px; min-width: 270px; overflow: hidden; padding: 0;&quot;&gt; &lt;a href=&quot;https:&#x2F;&#x2F;mstdn.maud.io&#x2F;@m1sk9&#x2F;115613453651083916&quot; target=&quot;_blank&quot; style=&quot;align-items: center; color: #1C1A25; display: flex; flex-direction: column; font-family: system-ui, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, Oxygen, Ubuntu, Cantarell, &#x27;Fira Sans&#x27;, &#x27;Droid Sans&#x27;, &#x27;Helvetica Neue&#x27;, Roboto, sans-serif; font-size: 14px; justify-content: center; letter-spacing: 0.25px; line-height: 20px; padding: 24px; text-decoration: none;&quot;&gt; &lt;svg xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; xmlns:xlink=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xlink&quot; width=&quot;32&quot; height=&quot;32&quot; viewBox=&quot;0 0 79 75&quot;&gt;&lt;path d=&quot;M63 45.3v-20c0-4.1-1-7.3-3.2-9.7-2.1-2.4-5-3.7-8.5-3.7-4.1 0-7.2 1.6-9.3 4.7l-2 3.3-2-3.3c-2-3.1-5.1-4.7-9.2-4.7-3.5 0-6.4 1.3-8.6 3.7-2.1 2.4-3.1 5.6-3.1 9.7v20h8V25.9c0-4.1 1.7-6.2 5.2-6.2 3.8 0 5.8 2.5 5.8 7.4V37.7H44V27.1c0-4.9 1.9-7.4 5.8-7.4 3.5 0 5.2 2.1 5.2 6.2V45.3h8ZM74.7 16.6c.6 6 .1 15.7.1 17.3 0 .5-.1 4.8-.1 5.3-.7 11.5-8 16-15.6 17.5-.1 0-.2 0-.3 0-4.9 1-10 1.2-14.9 1.4-1.2 0-2.4 0-3.6 0-4.8 0-9.7-.6-14.4-1.7-.1 0-.1 0-.1 0s-.1 0-.1 0 0 .1 0 .1 0 0 0 0c.1 1.6.4 3.1 1 4.5.6 1.7 2.9 5.7 11.4 5.7 5 0 9.9-.6 14.8-1.7 0 0 0 0 0 0 .1 0 .1 0 .1 0 0 .1 0 .1 0 .1.1 0 .1 0 .1.1v5.6s0 .1-.1.1c0 0 0 0 0 .1-1.6 1.1-3.7 1.7-5.6 2.3-.8.3-1.6.5-2.4.7-7.5 1.7-15.4 1.3-22.7-1.2-6.8-2.4-13.8-8.2-15.5-15.2-.9-3.8-1.6-7.6-1.9-11.5-.6-5.8-.6-11.7-.8-17.5C3.9 24.5 4 20 4.9 16 6.7 7.9 14.1 2.2 22.3 1c1.4-.2 4.1-1 16.5-1h.1C51.4 0 56.7.8 58.1 1c8.4 1.2 15.5 7.5 16.6 15.6Z&quot; fill=&quot;currentColor&quot;&#x2F;&gt;&lt;&#x2F;svg&gt; &lt;div style=&quot;color: #787588; margin-top: 16px;&quot;&gt;Post by @m1sk9@mstdn.maud.io&lt;&#x2F;div&gt; &lt;div style=&quot;font-weight: 500;&quot;&gt;View on Mastodon&lt;&#x2F;div&gt; &lt;&#x2F;a&gt; &lt;&#x2F;blockquote&gt; &lt;script data-allowed-prefixes=&quot;https:&#x2F;&#x2F;mstdn.maud.io&#x2F;&quot; async src=&quot;https:&#x2F;&#x2F;mstdn.maud.io&#x2F;embed.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;h2 id=&quot;devcontainer-niqiu-merarerukoto&quot;&gt;DevContainer に求められること&lt;a class=&quot;zola-anchor&quot; href=&quot;#devcontainer-niqiu-merarerukoto&quot; aria-label=&quot;Anchor link for: devcontainer-niqiu-merarerukoto&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-node-js-nobaziyonguan-li-gadekiru&quot;&gt;1. Node.js のバージョン管理ができる&lt;a class=&quot;zola-anchor&quot; href=&quot;#1-node-js-nobaziyonguan-li-gadekiru&quot; aria-label=&quot;Anchor link for: 1-node-js-nobaziyonguan-li-gadekiru&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Node.js のバージョン管理には mise や asdf などの外部ツールを使うのが一般的ですが，DevContainer の場合は，それらは&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;hub.docker.com&#x2F;_&#x2F;node&quot;&gt;単一の Docker Image&lt;&#x2F;a&gt; なのでバージョン管理が簡単です． (Renovate にも更新をさせることができる)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-quan-tenokai-fa-huan-jing-wo-docker-container-nei-dewan-jie-dekiru&quot;&gt;2. 全ての開発環境を Docker Container 内で完結できる&lt;a class=&quot;zola-anchor&quot; href=&quot;#2-quan-tenokai-fa-huan-jing-wo-docker-container-nei-dewan-jie-dekiru&quot; aria-label=&quot;Anchor link for: 2-quan-tenokai-fa-huan-jing-wo-docker-container-nei-dewan-jie-dekiru&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;DevContainer は起動した Docker Container に VSCode で接続する仕組みなので， DB などそれ以外の環境を DevContainer に含めれれば，ローカルに何もインストールせずに開発が完結します．&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-rokaruniying-xiang-woyu-enai&quot;&gt;3. ローカルに影響を与えない&lt;a class=&quot;zola-anchor&quot; href=&quot;#3-rokaruniying-xiang-woyu-enai&quot; aria-label=&quot;Anchor link for: 3-rokaruniying-xiang-woyu-enai&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;何と言ってもこれ．&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;基本ローカルはクリーンにしておきたいので，DevContainer 内に全ての開発環境を閉じ込めれば，ローカルに影響を与えずに済みます．&lt;&#x2F;p&gt;
&lt;h2 id=&quot;zui-xiao-gou-cheng-de-devcontainer-wozuo-tutemiru&quot;&gt;最小構成で DevContainer を作ってみる&lt;a class=&quot;zola-anchor&quot; href=&quot;#zui-xiao-gou-cheng-de-devcontainer-wozuo-tutemiru&quot; aria-label=&quot;Anchor link for: zui-xiao-gou-cheng-de-devcontainer-wozuo-tutemiru&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;DevContainer を作るにはプロジェクトルートに &lt;code&gt;.devcontainer&lt;&#x2F;code&gt; ディレクトリを作成し，その中に &lt;code&gt;devcontainer.json&lt;&#x2F;code&gt; を作成します．これが DevContainer の設定ファイルになります．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; class=&quot;language-json z-code&quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-json&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;name&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Node.js 24.11.1 DevContainer&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;build&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-json&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;dockerfile&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Dockerfile&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;  &lt;span class=&quot;z-punctuation z-section z-mapping z-end z-json&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;customizations&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-json&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;vscode&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-json&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;      &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;extensions&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-sequence z-begin z-json&quot;&gt;[&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;        &lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;dbaeumer.vscode-eslint&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-sequence z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;        &lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;esbenp.prettier-vscode&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;      &lt;span class=&quot;z-punctuation z-section z-sequence z-end z-json&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-mapping z-end z-json&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;  &lt;span class=&quot;z-punctuation z-section z-mapping z-end z-json&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-end z-json&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;DevContainer に接続する VSCode は Standalone &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; となるので，&lt;code&gt;customizations&lt;&#x2F;code&gt; フィールドで接続先の VSCode で使いたい拡張機能をインストールしたり，設定を追加したりできます．つまり&lt;strong&gt;開発環境を他のメンバーと共有でき，なおかつ完全分離ができるわけです&lt;&#x2F;strong&gt;．&lt;&#x2F;p&gt;
&lt;p&gt;次に &lt;code&gt;Dockerfile&lt;&#x2F;code&gt; を作成します．この &lt;code&gt;Dockerfile&lt;&#x2F;code&gt; で作成する Docker Image を実際にコンテナ内で使うことになります．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;dockerfile&quot; class=&quot;language-dockerfile z-code&quot;&gt;&lt;code class=&quot;language-dockerfile&quot; data-lang=&quot;dockerfile&quot;&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;FROM&lt;&#x2F;span&gt; node:&lt;span class=&quot;z-entity z-name z-enum z-tag-digest&quot;&gt;24.11.1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; 必要なら追加のツールをここでインストールすることもできる
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; RUN apt-get update &amp;amp;&amp;amp; apt-get install -y ...
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;これで Node.js v24.11.1 を使う DevContainer の完成です．
起動するには VSCode のコマンドパレットから &quot;Dev Containers: Reopen in Container&quot; を実行します．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;contain-nodejs-in-devcontainer&#x2F;vscode-1.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align: center; font-size: 0.80em; color: #888; margin-top: 8px;&quot;&gt;
    イメージの更新や設定変更をしたら &quot;Rebuild and Reopen in Container&quot; を実行しよう
&lt;&#x2F;div&gt;
&lt;p&gt;すると Docker Image のビルド， DevContainer のインストールが行われ，VSCode がコンテナに接続します．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;contain-nodejs-in-devcontainer&#x2F;vscode-2.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align: center; font-size: 0.80em; color: #888; margin-top: 8px;&quot;&gt;
    パッと見は SSH Remote と同じ
&lt;&#x2F;div&gt;
&lt;p&gt;試しに以下のような静的テキストを返す簡易 HTTP サーバーを作成してみます．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; class=&quot;language-js z-code&quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-import z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-control z-import z-ts&quot;&gt;import&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-alias z-ts&quot;&gt;http&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-from z-ts&quot;&gt;from&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;http&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;http&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;createServer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;writeHead&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;200&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;content-type&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;text&#x2F;plain; charset=utf-8&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;Hello, World!&lt;span class=&quot;z-constant z-character z-escape z-ts&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;3000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;server&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;listen&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-console z-ts&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-console z-ts&quot;&gt;log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;Server is running at http:&#x2F;&#x2F;localhost:&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;ポートは自動的に Forward されるので，コンテナ内でサーバーを起動すれば，ローカルホストからアクセスできます．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;contain-nodejs-in-devcontainer&#x2F;vscode-3.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;contain-nodejs-in-devcontainer&#x2F;firefox.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align: center; font-size: 0.80em; color: #888; margin-top: 8px;&quot;&gt;
    簡単だね!
&lt;&#x2F;div&gt;
&lt;h1 id=&quot;node-modules-mo-devcontainer-nibi-ziip-meyou&quot;&gt;node_modules も DevContainer に閉じ込めよう&lt;a class=&quot;zola-anchor&quot; href=&quot;#node-modules-mo-devcontainer-nibi-ziip-meyou&quot; aria-label=&quot;Anchor link for: node-modules-mo-devcontainer-nibi-ziip-meyou&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h1&gt;
&lt;p&gt;Node.js のプロジェクトでは &lt;code&gt;node_modules&lt;&#x2F;code&gt; ディレクトリが大量に生成され，ローカルにインストールされると非常に邪魔です．(サプライチェーン攻撃にも利用される)&lt;&#x2F;p&gt;
&lt;p&gt;デフォルトの DevContainer の挙動では，ホストのプロジェクトディレクトリがコンテナ内にマウントされるため，&lt;code&gt;node_modules&lt;&#x2F;code&gt; もホストに作成されてしまいます．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;m1sk9.dev&#x2F;posts&#x2F;contain-nodejs-in-devcontainer&#x2F;nodejs-meme.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align: center; font-size: 0.80em; color: #888; margin-top: 8px;&quot;&gt;
    node_modules black hole
&lt;&#x2F;div&gt;
&lt;p&gt;これを防ぐ方法として Docker の Volue Trick を利用して，&lt;code&gt;node_modules&lt;&#x2F;code&gt; をコンテナ内に閉じ込める方法があります．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; class=&quot;language-json z-code&quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;z-source z-json&quot;&gt;  &lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;mounts&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;: &lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-sequence z-begin z-json&quot;&gt;[&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;    &lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;source=project_node_modules,target=&#x2F;workspace&#x2F;node_modules,type=volume&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;  &lt;span class=&quot;z-punctuation z-section z-sequence z-end z-json&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;devcontainer-hamo-fa-nozhang-dehanai&quot;&gt;DevContainer は魔法の杖ではない&lt;a class=&quot;zola-anchor&quot; href=&quot;#devcontainer-hamo-fa-nozhang-dehanai&quot; aria-label=&quot;Anchor link for: devcontainer-hamo-fa-nozhang-dehanai&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h1&gt;
&lt;p&gt;ここまで散々 DevContainer のことを持ち上げましたが，DevContainer でもサプライチェーン攻撃を完全に防げるわけではありません．
侵害された npm パッケージをインストールすれば，コンテナ内では攻撃を受けます．&lt;&#x2F;p&gt;
&lt;p&gt;ただ DevContainer は Docker Container の中に開発環境を構築するので，万が一攻撃を受けたとしてもそのコンテナを破棄すればローカルには影響を与えません．&lt;&#x2F;p&gt;
&lt;h1 id=&quot;ignore-scripts-opusiyonwoshi-u&quot;&gt;&lt;code&gt;--ignore-scripts&lt;&#x2F;code&gt; オプションを使う&lt;a class=&quot;zola-anchor&quot; href=&quot;#ignore-scripts-opusiyonwoshi-u&quot; aria-label=&quot;Anchor link for: ignore-scripts-opusiyonwoshi-u&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h1&gt;
&lt;p&gt;npm や yarn, pnpm にはインストール時に &lt;code&gt;--ignore-scripts&lt;&#x2F;code&gt; オプションを付与することで，パッケージのインストール時に実行されるスクリプトを無効化できます．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;npm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; ci&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;ignore-scripts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;yarn&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;ignore-scripts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;pnpm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;ignore-scripts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Shai Hulud のような攻撃はインストール時にスクリプトを実行することで行われるため，このオプションを付与することで攻撃を防げる可能性があります．&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Deno の v2.0 リリース時に公式から公開された PV &quot;Programming Should Be Simple&quot; は npm の脆弱さをいじってるシーンがある．&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;PHP は別に業務でも書いてないしなんなら嫌いな言語の1つだが，大学の講義で仕方なく使わざる終えなかったので DevContainer に封じ込めた．&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Remote Connection のような挙動をするので，ローカルの VSCode とは別に拡張機能や設定を持てる．&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>GnuPGのセットアップ</title>
		<published>2025-11-08T00:00:00+00:00</published>
		<updated>2025-11-08T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://m1sk9.dev/posts/setup-gnupg/"/>
		<id>https://m1sk9.dev/posts/setup-gnupg/</id>
    
		<content type="html" xml:base="https://m1sk9.dev/posts/setup-gnupg/">&lt;p&gt;初期化したときや新しい Laptop を迎えたときに行う GnuPG のセットアップについての備忘録．&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gnupg-to-pinentry-mac-noinsutoru&quot;&gt;GnuPG と pinentry-mac のインストール&lt;a class=&quot;zola-anchor&quot; href=&quot;#gnupg-to-pinentry-mac-noinsutoru&quot; aria-label=&quot;Anchor link for: gnupg-to-pinentry-mac-noinsutoru&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;GnuPG と pinentry-mac をインストールする．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;brew&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install gnupg pinentry-mac&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;gnupg-noshe-ding&quot;&gt;GnuPG の設定&lt;a class=&quot;zola-anchor&quot; href=&quot;#gnupg-noshe-ding&quot; aria-label=&quot;Anchor link for: gnupg-noshe-ding&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Apple Silicon では Homebrew が配置する pinentry-mac のパスが異なるため， GnuPG の設定ファイルに pinentry-mac のパスを指定する必要がある．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;pinentry-program &#x2F;opt&#x2F;homebrew&#x2F;bin&#x2F;pinentry-mac&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-expansion z-tilde&quot;&gt;&lt;span class=&quot;z-variable z-language z-tilde z-shell&quot;&gt;~&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;.gnupg&#x2F;gpg-agent.conf&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;gpgconf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;kill&lt;&#x2F;span&gt; gpg-agent&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;jian-noinpoto&quot;&gt;鍵のインポート&lt;a class=&quot;zola-anchor&quot; href=&quot;#jian-noinpoto&quot; aria-label=&quot;Anchor link for: jian-noinpoto&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;YubiKey に保存してある鍵サーバから副鍵をインポートする．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;gpg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;card-edit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;gpg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; fetch&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;ssh-noshu-tong-que-ren&quot;&gt;SSH の疎通確認&lt;a class=&quot;zola-anchor&quot; href=&quot;#ssh-noshu-tong-que-ren&quot; aria-label=&quot;Anchor link for: ssh-noshu-tong-que-ren&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;鍵をインポートすると自動で SSH 鍵もインポートされるため，SSH の疎通確認を行う．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;ssh-add&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;L &lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; 鍵が表示されることを確認&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;ssh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;T&lt;&#x2F;span&gt; git@github.com&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Hi m1sk9! You&amp;#39;ve successfully authenticated, but GitHub does not provide shell access.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;shu-ming-tesuto&quot;&gt;署名テスト&lt;a class=&quot;zola-anchor&quot; href=&quot;#shu-ming-tesuto&quot; aria-label=&quot;Anchor link for: shu-ming-tesuto&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;最後に署名テストを行う．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;TEST&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-pipe z-shell&quot;&gt;|&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;gpg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;clearsign&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Rust における Docker Image の軽量化を考えてみる</title>
		<published>2025-02-03T00:00:00+00:00</published>
		<updated>2025-02-03T00:00:00+00:00</updated>
		<link rel="alternate" type="text/html" href="https://m1sk9.dev/posts/docker-image-optimization-hint/"/>
		<id>https://m1sk9.dev/posts/docker-image-optimization-hint/</id>
    
		<content type="html" xml:base="https://m1sk9.dev/posts/docker-image-optimization-hint/">&lt;p&gt;ここ2年くらいずっと保守しているプロジェクトに babyrite というものがある．これはメッセージリンクからプレビューを生成しそれを埋め込みとして返す Discord Bot の一つ．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;assets&#x2F;post&#x2F;image&#x2F;docker-image-optimization-hint&#x2F;babyrite-using.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;m1sk9&#x2F;babyrite&quot;&gt;m1sk9&#x2F;babyrite: A lightweight, fast citation message Discord bot.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;このような Bot は色んな人が開発してホストして外部公開してくれている&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;．もちろんそれらの Bot を使っても構わないが，このようなメッセージ取得系の Bot は本来外部に公開されてはいけないデリケートなメッセージも取得することがあり，私のような捻くれオタクはこのような Bot を使うことに懐疑的．(だってソースコード公開されているわけでもないし)&lt;&#x2F;p&gt;
&lt;p&gt;そのようなオタク向けに babyrite は Docker Image を GitHub Container Registry (ghcr.io) 経由で公開している．&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;m1sk9&#x2F;babyrite&#x2F;blob&#x2F;main&#x2F;CHANGELOG.md#0130-2024-10-23&quot;&gt;babyrite v0.13.0&lt;&#x2F;a&gt; ではこの Docker Image を大胆な軽量化に成功したのでメモ的に書いておこうと思う．&lt;&#x2F;p&gt;
&lt;h2 id=&quot;multi-stage-builds-wohuo-yong-suru&quot;&gt;Multi-stage builds を活用する&lt;a class=&quot;zola-anchor&quot; href=&quot;#multi-stage-builds-wohuo-yong-suru&quot; aria-label=&quot;Anchor link for: multi-stage-builds-wohuo-yong-suru&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Docker Image ビルド時に &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;docs.docker.com&#x2F;build&#x2F;building&#x2F;multi-stage&#x2F;&quot;&gt;Multi-stage builds&lt;&#x2F;a&gt; を使用する．実際これが一番手っ取り早い最適方法だったりする．&lt;&#x2F;p&gt;
&lt;p&gt;babyrite は Rust で書かれているため， Rust の公式イメージを使用してリリースビルドを行う．&lt;&#x2F;p&gt;
&lt;p&gt;速度を求めるならここのイメージも色々選定が必要そうだが，Rust を使ってる時点で遅すぎるコンパイルという十字架を背負うので私は考えていない． (そのコンパイルも結局はマシン側の性能に依存する)&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;dockerfile&quot; class=&quot;language-dockerfile z-code&quot;&gt;&lt;code class=&quot;language-dockerfile&quot; data-lang=&quot;dockerfile&quot;&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;FROM&lt;&#x2F;span&gt; rust:&lt;span class=&quot;z-entity z-name z-enum z-tag-digest&quot;&gt;1.80.1-bookworm&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;as&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-stage-name&quot;&gt;Builder&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;WORKDIR &lt;&#x2F;span&gt;&#x2F;root&#x2F;app
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; --chown=root:root . .
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;RUN &lt;&#x2F;span&gt;cargo build --release --bin babyrite
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;この成果物を後述の実行ステージのイメージに移動する．&lt;code&gt;COPY&lt;&#x2F;code&gt; に &lt;code&gt;--from&lt;&#x2F;code&gt; prefix で指定することで移動可能．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;dockerfile&quot; class=&quot;language-dockerfile z-code&quot;&gt;&lt;code class=&quot;language-dockerfile&quot; data-lang=&quot;dockerfile&quot;&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;COPY --from=builder --chown=root:root &#x2F;root&#x2F;app&#x2F;target&#x2F;release&#x2F;babyrite &#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;この Multi-stage builds に関してはネット上に大量に記事があるためここで解説はしない．使い方等は公式ドキュメントを読むが一番だ．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;docs.docker.com&#x2F;build&#x2F;building&#x2F;multi-stage&#x2F;&quot;&gt;Multi-stage | Docker Docs&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;shi-xing-sutezinoimezini-distroless-woshi-yong-suru&quot;&gt;実行ステージのイメージに Distroless を使用する&lt;a class=&quot;zola-anchor&quot; href=&quot;#shi-xing-sutezinoimezini-distroless-woshi-yong-suru&quot; aria-label=&quot;Anchor link for: shi-xing-sutezinoimezini-distroless-woshi-yong-suru&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;さて，次はこのビルドした babyrite のバイナリをどこで実行しようという話になる．&lt;&#x2F;p&gt;
&lt;p&gt;babyrite は正直 Discord API とのやり取りしか行わず，他の Bot のようにログ記録機能を備えているわけでもない．&lt;&#x2F;p&gt;
&lt;p&gt;そのため，単純な Ubuntu や Debian のイメージを使っても問題はないのだが，このようなイメージは無駄なパッケージが含まれており，折角の成果物が数サイズなのに実行イメージだけで 100MB 近く埋まってしまう．&lt;&#x2F;p&gt;
&lt;p&gt;そこで軽量イメージとして主流になってる Distroless を採用してみようと考えた．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GoogleContainerTools&#x2F;distroless&#x2F;&quot;&gt;GoogleContainerTools&#x2F;distroless: 🥑 Language focused docker images, minus the operating system.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;distroless-toha&quot;&gt;Distroless とは&lt;a class=&quot;zola-anchor&quot; href=&quot;#distroless-toha&quot; aria-label=&quot;Anchor link for: distroless-toha&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Google &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; がメンテしているイメージ群で，最低限必要な設定や実行ファイルだけが含まれているため，コンテナイメージのサイズを小さくすることができる．&lt;&#x2F;p&gt;
&lt;p&gt;ベストプラクティスかどうかと問われると私はその線で詳しくはないので以下の記事に説明を丸投げしようと思う&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;qiita.com&#x2F;t_katsumura&#x2F;items&#x2F;462e2ae6321a9b5e473e&quot;&gt;セキュアで軽量なdistrolessコンテナを作成する #Docker - Qiita&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;babyrite ではこのような形で最終的な実行形態にしている．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;dockerfile&quot; class=&quot;language-dockerfile z-code&quot;&gt;&lt;code class=&quot;language-dockerfile&quot; data-lang=&quot;dockerfile&quot;&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;FROM&lt;&#x2F;span&gt; gcr.io&#x2F;distroless&#x2F;cc-debian12 &lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;AS&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-stage-name&quot;&gt;runner&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; --from=&lt;span class=&quot;z-variable z-stage-name&quot;&gt;builder&lt;&#x2F;span&gt; --chown=root:root &#x2F;root&#x2F;app&#x2F;target&#x2F;release&#x2F;babyrite &#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-dockerfile&quot;&gt;CMD &lt;&#x2F;span&gt;[&lt;span class=&quot;z-string z-quoted z-double z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-dockerfile&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.&#x2F;babyrite&lt;span class=&quot;z-punctuation z-definition z-string z-end z-dockerfile&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;非常にシンプルな最適化を加えることで 60MB ほどの減量に成功した．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;assets&#x2F;post&#x2F;image&#x2F;docker-image-optimization-hint&#x2F;docker-image-size.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;alpine-ha&quot;&gt;Alpine は？&lt;a class=&quot;zola-anchor&quot; href=&quot;#alpine-ha&quot; aria-label=&quot;Anchor link for: alpine-ha&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;やめたほうがよさそう&lt;&#x2F;strong&gt;．この話については inductor さんの記事が簡潔で分かりやすい．&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;blog.inductor.me&#x2F;entry&#x2F;alpine-not-recommended&quot;&gt;軽量Dockerイメージに安易にAlpineを使うのはやめたほうがいいという話 - inductor&#x27;s blog&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;omake-konpairuopusiyonwoli-yong-suru&quot;&gt;おまけ: コンパイルオプションを利用する&lt;a class=&quot;zola-anchor&quot; href=&quot;#omake-konpairuopusiyonwoli-yong-suru&quot; aria-label=&quot;Anchor link for: omake-konpairuopusiyonwoli-yong-suru&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;この記事を書いてる最中に思いついたので追加で書いておこうと思う．ただリリースビルドの時間がバカにならないので babyrite には取り込んでいない．&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;バイナリのコンパイルに対しても最適化を行い，バイナリサイズを削減することも可能だ．&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;reference&#x2F;profiles.html&quot;&gt;Profiles - The Cargo Book&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;commands&#x2F;cargo-build.html&quot;&gt;cargo build - The Cargo Book&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; に以下の設定を加えてコンパイルしてみる．&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;profile&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;lto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-toml&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;strip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-toml&quot;&gt;false&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;codegen-units&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-toml&quot;&gt;8&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; build&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;上の設定を行うと Cargo は次のような挙動でリリースビルドを行うようになる:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Link Time Optimization (lto): &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
&lt;ul&gt;
&lt;li&gt;リンク時間が長くなる (=総合的にはコンパイル時間が長くなる) 代償として，プログラム全体の解析を行い，より最適化されたコードを生成します．&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;strip: &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
&lt;ul&gt;
&lt;li&gt;バイナリからシンボル，またはデバッグ情報を取り除くようになります．&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;codegen-units: &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
&lt;ul&gt;
&lt;li&gt;Cargo がリリースビルド時に使用する並列コード生成ユニットの数を指定します．このユニット数が少なければ少ないほどバイナリサイズは最適化されるが，同時にコンパイル時間は長くなる．
結果はこんな感じ:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;オプション&lt;&#x2F;th&gt;&lt;th&gt;サイズ&lt;&#x2F;th&gt;&lt;th&gt;コンパイル時間&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;あり&lt;&#x2F;td&gt;&lt;td&gt;14M&lt;&#x2F;td&gt;&lt;td&gt;4m 36s&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;なし&lt;&#x2F;td&gt;&lt;td&gt;17M&lt;&#x2F;td&gt;&lt;td&gt;2m 43s&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;たかが数サイズ程度の削減で，コンパイル時間と天秤にかけると私的にはこれは無しかなとは思っている．&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;イケBot とか&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Google は嫌いだけど Distroless は嫌いじゃない！&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Shell がないのでちょっとした処理を追加できないという指摘については賛同したい&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;reference&#x2F;profiles.html#lto&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;reference&#x2F;profiles.html#strip&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;macOS 及び Linux でのお話．&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;7&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;reference&#x2F;profiles.html#codegen-units&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
	</entry>
</feed>
