ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

PowerShell (Windows) で Docker コンテナにホストディレクトリをデータボリュームとしてマウントする際に pwd 相当のことをしたい

試した環境

  • Windows 10 Home (Anniversary Update; 64-bit 版)
  • Docker Toolbox 1.12.0

前提知識

絶対パスで記述するためにどうするかが問題

Linux では以下のように pwd コマンドを使うのが一般的かと思います。

docker run -v $(pwd)/path/to/target:/container/path ...

じゃあ Windows (PowerShell) でどうするのか、というのが問題です。 PowerShell にも pwd コマンド相当の Get-Location コマンドレット があるのですが、これをそのまま使うとパスの形式が通常の Windows のパス表記の形式になるので、docker コマンドの -v オプションに渡せません。

Write-Output "$(Get-Location)/path/to/target"
# => C:\Users\userName\Documents\project/path/to/target
# 本当は /c/Users/userName/Cocuments/project/path/to/target という形式で欲しい

# 実際にやってみると以下のようなエラーが出る。
docker run -v "$(Get-Location)/path/to/target:/container/path" ...
C:\Program Files\Docker Toolbox\docker.exe: Error response from daemon: Invalid bind mount spec "C:\\Users\\userName\\Documents\\project/path/to/target:/container/path": invalid mode: /container/path.
See 'C:\Program Files\Docker Toolbox\docker.exe run --help'.

雑に対応する

そんなわけで、以下のように Windows の通常のパスの表記を Linux ぽい感じに変換する関数を定義して使っています。

function pwd_as_linux {
  "/$((pwd).Drive.Name.ToLowerInvariant())/$((pwd).Path.Replace('\', '/').Substring(3))"
}

# 実際使う場合は以下のような感じ。
docker run -v "$(pwd_as_linux)/path/to/target:/container/path" ...

関数を定義するまでもなく変数に格納して使いたいって感じなら以下のようにもできます。

# Linux 風のパス形式。
$pwd_as_linux = "/$((pwd).Drive.Name.ToLowerInvariant())/$((pwd).Path.Replace('\', '/').Substring(3))"

# 使う。
docker run -v ${pwd_as_linux}/path/to/target:/container/path ...

Docker Engine 側で通常の Windows のパス形式を受け付けてくれたらいいのですが、コロンが区切りに使われてるから難しいんだろうなぁと思ったり。

参考ページ