ホストマシンを再起動すると、Dockerコンテナに対するSSH_AUTH_SOCKのマウントがうまくいかない
事象
一度コンテナを立ち上げ、そのあとホストマシン(Ubuntu)を再起動。
再起動後に再びコンテナを立ち上げようとするとマウントできない旨のエラーが出る。
Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting "/tmp/ssh-ZyloNEwSAswN/agent.1551" to rootfs at "/tmp/ssh-ZyloNEwSAswN/agent.1551": mount /tmp/ssh-ZyloNEwSAswN/agent.1551:/tmp/ssh-ZyloNEwSAswN/agent.1551 (via /proc/self/fd/7), flags: 0x5000: not a directory: unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type
環境
- Ubuntu24.04 (WSL)
- Docker (version 27.1.1)
- devcontainer cli (version 0.66.0)
前提
Ubuntuで ssh-agent
を起動するとソケットは /tmp/ssh-xxxxx/agent.xxx
に配置される。 この場所は echo $SSH_AUTH_SOCK
で確認できる。
docker compose
を用いてコンテナ上を立ち上げる際、Ubuntuの ssh-agent
を引き継ぐには以下のようにenvとvolumesを設定する(ことがネットで散見された)。
docker-compose.yml
services:
app:
build:
context: .
dockerfile: ./Dockerfile
environment:
- SSH_AUTH_SOCK=$SSH_AUTH_SOCK
volumes:
- $SSH_AUTH_SOCK:$SSH_AUTH_SOCK
tty: true
私は実際には docker compose
を使っておらず、devcontainer cli
を使用している。
.devcontainer/devcontainer.json
{
"name": "Ubuntu",
"dockerComposeFile": "docker-compose.yml",
"service": "app"
}
実行コマンド。(docker compose up と docker compose execと同じようなコマンド)
$ devcontainer up --workspace-folder .
$ devcontainer exec --workspace-folder . bash
原因
Ubuntu再起動後に ssh-agent
を起動すると、前回とは異なる位置にソケットが配置される。(/tmp/ssh-xxxxx/agent.xxx
という形式なので)
そしてdocker-compose.ymlに記載したvolumesはビルド時に固定されるため、あとから変えることはできない。
そのためUbuntu再起動後にコンテナを立ち上げようとすると、(ビルド時に固定した)再起動前のソケットをマウントしようと試みて失敗する。
対処法
鍵情報をコンテナの ~/.ssh/ に書き込んだり、コンテナを作り直したりすることで解決はできるらしい。
別の方法はないかと探してみたところ、どうやら ssh-agent
のオプションでソケットの配置場所を設定するオプションがあるらしい。
man ssh-agent
の結果
-a bind_address
Bind the agent to the Unix-domain socket bind_address. The default is
$TMPDIR/ssh-XXXXXXXXXX/agent.<ppid>.
これを使えばソケットの配置場所が固定されるので問題が解決できる。
具体的には .bash_profile
に下のように記載すれば良い。
$ cat ~/.bash_profile
if [ -z "$SSH_AUTH_SOCK" ]; then
# Check for a currently running instance of the agent
RUNNING_AGENT="`ps -ax | grep 'ssh-agent -s' | grep -v grep | wc -l | tr -d '[:space:]'`"
if [ "$RUNNING_AGENT" = "0" ]; then
mkdir -p /tmp/ssh
# Launch a new instance of the agent
ssh-agent -s -a /tmp/ssh/agent.sock &> $HOME/.ssh/ssh-agent
fi
eval `cat $HOME/.ssh/ssh-agent` >& /dev/null
fi
if [ -f ~/.bashrc ] ; then
. ~/.bashrc
fi
Discussion