DockerコンテナでTCPポートをListenしようとしたら、"Error response from daemon: Ports are not available: listen tcp 0.0.0.0:1080: bind: An attempt was made to access a socket in a way forbidden by its access permissions."となってしまう現象の解消方法 → winnatサービスが原因でした

n番煎じですが、備忘録として書きます。

目次


環境

  • Windows 10 Pro 64bit 22H2 (ビルド: 19045.3031)
    • Hyper-V 有効
    • Windows ハイパーバイザー プラットフォーム 有効
    • LinuxWindows サブシステム (WSL2) 有効
      wsl --versionの出力を一部抜粋
      • WSL バージョン: 1.2.5.0
      • カーネル バージョン: 5.15.90.1
    • 仮想マシン プラットフォーム 有効
  • Docker Desktop 4.19.0

症状

DockerでTCP 1080ポートをListenするコンテナを立ち上げようとしたら、下記のエラーメッセージが出てStartできませんでした。

Error response from daemon: Ports are not available: listen tcp 0.0.0.0:1080: bind: An attempt was made to access a socket in a way forbidden by its access permissions.

確認 or 試してみてダメだったこと

エラーメッセージでググって出てきた解決策のうち、下記を試してみましたが、コンテナをStartしようとすると同じエラーメッセージが出てしまいました。

  • ポートを使用しているプログラムの終了 *1
  • Dockerの再起動
  • OSの再起動

(試してないこと)

  • Hyper-Vを一度無効化してから再度有効化する

確認して該当したこと

ポートのListenを拒否するWindowsのポート除外範囲 *2 に当該ポートが含まれた設定があるかを下記のコマンドで確認しました。
netsh int ipv4 show excludedportrange protocol=tcp

今回の場合には、出力結果に当該ポートが含まれる設定が見つかりました。

PS C:\Windows\system32> netsh int ipv4 show excludedportrange protocol=tcp

プロトコル tcp ポート除外範囲

開始ポート    終了ポート
----------    --------
      1050        1149
      1150        1249
      1250        1349
      1605        1704
      1705        1804
      1805        1904
      5357        5357
     13200       13299
     13300       13399
     13400       13499
     50000       50059     *

* - 管理されている除外ポート。

PS C:\Windows\system32>

解消方法

winnatサービスの再起動によりWindowsのポート除外範囲として予約されている範囲がリセットされたと思われ、DockerコンテナをStartしてポートをListenすることができましたので、その手順を紹介します。

C:\Windows\system32>net stop winnat

Windows NAT Driver サービスは正常に停止されました。


C:\Windows\system32>net start winnat

Windows NAT Driver サービスは正常に開始されました。


C:\Windows\system32>
PS C:\Windows\system32> Restart-Service -Name winnat
PS C:\Windows\system32>

(参考) winnatサービスを再起動してエラーが解消した後のポート除外範囲

PS C:\Windows\system32> netsh int ipv4 show excludedportrange protocol=tcp

プロトコル tcp ポート除外範囲

開始ポート    終了ポート
----------    --------
      5357        5357
     50000       50059     *

* - 管理されている除外ポート。

PS C:\Windows\system32>

参考にさせていただいたページ

*1:PowerShellnetstat -ano | Select-String ":1080"を実行して調査しましたが、該当するプログラムはありませんでした。

*2:Windowsのポート除外範囲については、香り屋様のページに詳しく書かれていました。

PE37

コロナによる外出自粛で暇だったので、 Problem 37(日本語訳)に取り組む。

ハマるかなと思っていたが、Pythonで書いたので、問題文をそのままコードに落としたような実装で解くことができた。
特にここで書くようなメモもないかな。

それにしても、Pythonの文字列操作やら、リスト・セット(集合)は使いやすい。

PE36

Problem 36(日本語訳)がすんなり解けた。嬉しい。

例によってPythonで文字列操作ゴリ押ししようかと思ったが、 ビット列を正しく生成する形でやるのが正攻法のような気がしたので取り組んでみた。

実際、この方法だと高速なので、1兆くらいまでであれば割とすぐに答えが出る。

当初ビット列生成に苦しんでいたが、それよりも、10進数での回文数の判定をミスってることに気が付かず、 ビット列生成を延々と怪しんであちこち確かめていたので、解法が分かっていた割には思ったより時間がかかってしまった。

PE35

しばらく考えていたけど効率的な方法が思いつかず、適当に素数と巡回数(?)を作ってぶつける方法であっさり解けてしまった。

今回はスマホだけで全部書いてうまくいった。
Pythonで書くと、こういった雑な感じで作るときに楽にできるので有り難い。

1問ずつ順調に解けているので、このままペースを維持していきたい。

PE34

どうもお久しぶりです。
1年半近く(!)かかって、ようやくProblem 34を解けたので記念真紀子

できるだけ連続した番号の問題を解いていこうと考えていたが、 どうにも解法がわからんので、諦めてProblem 38に挑戦。

PE38 - BPM Memo

こんな事も書いてましたが、他の問題も難しく、、Project Euler自体放置してた。

言い訳はここらへんにして、本題。

1週間位前、電車に乗っているときに、ふと何かが降りてきたような気がして
iPhoneのちっちゃいソフトキーボードで書いてみたものの、駅につくまでに間に合わず、PCで再挑戦した。

単純に回して探索するのは論外として、
センスが無いので、探索する数の範囲をどう決めるかで長らく悩んで嵌っていた。

上で書いた、電車に乗っているときに降ってきたこととして、
数の桁数を決めて調べる方針として、
「その桁数を超えない範囲」で、「各桁の数の階乗がその桁数を超えない数」を調べれば良さそうだ、ということだった。
これでかなり小さな探索範囲になるので、早速実装してみたところ、なんとうまく行かない。。。

じっくり考えてわかったことだが、
上位桁に0のような階乗が小さい数がほとんど含まれるようなケースを考えると、
下位桁では「各桁の数の階乗がその桁数を超える数」も含めないといけない場合がありそうだった。

「指定桁数を超えない範囲」という点だけを制約として、再度書き直してみて、ようやく正解できた。

PE38

できるだけ連続した番号の問題を解いていこうと考えていたが、
どうにも解法がわからんので、諦めてProblem 38に挑戦。

電車の中でPythonでなんとなく書いて回してみるまでは良かったが、
すごい時間がかかるし熱いしバッテリーがガンガン減る。
1分ルールを満たせないので途中で止める。

後で気がついたのだが、問題文中の  n > 1 の条件をすっかり忘れていた。
これだったらそもそも 987654321 が解答になるが
そんなはずはないだろうということで、帰った後でゆっくり考えた。

9桁のパンデジタル数であることと、上記の条件を合わせて考えていると、
10000 の連結積では n\leq2 でも10桁となり、
桁数オーバーになることに気がついた。
これを制約として探索して無事に正解した。

PE33

組み合わせ総数は大したことないが、
精度不足で正解を出せないんじゃないかな、と考えたりしていたせいで
変な実装して全然走らせられなかったが、
頭を冷やして(寝ぼけていた状態で)愚直に実装し、あっさりと正解できた。