dockerコマンドを通してlinuxのsocket通信を確認
GOAL
dockerCLIとdockerdとのソケット通信を確認してみます。
環境
EC2を立ち上げ、ssmで接続して確認していきます。
例:↓↓↓↓
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "${local.env}-main-vpc"
}
}
resource "aws_subnet" "public-1a" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "ap-northeast-1a"
map_public_ip_on_launch = true
tags = {
Name = "${local.env}-public-subnet-1a"
}
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${local.env}-main-igw"
}
}
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
tags = {
Name = "${local.env}-public-route-table"
}
}
resource "aws_route_table_association" "public_association_1a" {
subnet_id = aws_subnet.public-1a.id
route_table_id = aws_route_table.public.id
}
resource "aws_security_group" "app_instance" {
vpc_id = aws_vpc.main.id
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${local.env}-app-instance-security-group"
}
}
resource "aws_instance" "app" {
ami = "ami-03d25459ad01ac2b9"
instance_type = "t3.micro"
subnet_id = aws_subnet.public-1a.id
vpc_security_group_ids = [aws_security_group.app_instance.id]
user_data = templatefile("./user_data.sh", {})
iam_instance_profile = aws_iam_instance_profile.ssm_profile.name
metadata_options {
http_tokens = "required"
}
tags = {
Name = "${local.env}-public-instance"
}
}
resource "aws_iam_role" "ssm_role" {
name = "ssm-role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [{
Effect = "Allow",
Principal = {
Service = "ec2.amazonaws.com"
},
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy_attachment" "ssm_attach" {
role = aws_iam_role.ssm_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
resource "aws_iam_instance_profile" "ssm_profile" {
name = "ssm-profile"
role = aws_iam_role.ssm_role.name
}
dockerコマンドを実行すると起きること
docker ps や docker run のようなコマンドを実行すると、実際には以下の流れで処理が進みます:
- Docker CLI(docker バイナリ) が起動し、引数をパースします。
- CLI は UNIXドメインソケット /var/run/docker.sock を通じて、
- dockerd(Dockerデーモン)に HTTP リクエスト を送信します。
- dockerd はこのリクエストを処理し、必要に応じてコンテナを作成・停止・情報を返却などを行います。
- 結果が CLI に戻り、整形された人間向けの出力として表示されます。
Docker CLIがUNIXドメインソケットを介して通信されることを確認
ssm-userでログインしている状態で、docker version
を実行するとclientの情報は返却されます。 が、socketに接続する権限が無いことがレスポンスされます。
sh-4.2$ docker version
Client:
Version: 25.0.8
API version: 1.44
Go version: go1.23.8
Git commit: 0bab007
Built: Fri May 16 16:25:26 2025
OS/Arch: linux/amd64
Context: default
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.44/version": dial unix /var/run/docker.sock: connect: permission denied
権限を確認すると、rootかdocker groupでwriteが実行できるようです。
ls -la /var/run/docker.sock
srw-rw---- 1 root docker 0 Jun 7 04:21 /var/run/docker.sock
rootで実行するとserverの情報も返ってきました。
sh-4.2$ sudo docker version
Client:
Version: 25.0.8
API version: 1.44
Go version: go1.23.8
Git commit: 0bab007
Built: Fri May 16 16:25:26 2025
OS/Arch: linux/amd64
Context: default
Server:
Engine:
Version: 25.0.8
API version: 1.44 (minimum version 1.24)
Go version: go1.23.8
Git commit: 71907ca
Built: Fri May 16 16:25:56 2025
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.7.27
GitCommit: 05044ec0a9a75232cad458027ca83437aae3f4da
runc:
Version: 1.2.4
GitCommit: 6c52b3fc541fb26fe8c374d5f58112a0a5dbda66
docker-init:
Version: 0.19.0
GitCommit: de40ad0
linuxのシステムコールを追跡
sh-4.2$ sudo strace -f -e trace=network docker version
strace: Process 9760 attached
strace: Process 9761 attached
strace: Process 9762 attached
strace: Process 9763 attached
strace: Process 9764 attached
[pid 9759] socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
[pid 9759] connect(3, {sa_family=AF_UNIX, sun_path="/var/run/docker.sock"}, 23) = 0
[pid 9759] getsockname(3, {sa_family=AF_UNIX}, [112->2]) = 0
[pid 9759] getpeername(3, {sa_family=AF_UNIX, sun_path="/run/docker.sock"}, [112->19]) = 0
Client:
Version: 25.0.8
API version: 1.44
Go version: go1.23.8
Git commit: 0bab007
Built: Fri May 16 16:25:26 2025
OS/Arch: linux/amd64
Context: default
Server:
Engine:
Version: 25.0.8
API version: 1.44 (minimum version 1.24)
Go version: go1.23.8
Git commit: 71907ca
Built: Fri May 16 16:25:56 2025
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.7.27
GitCommit: 05044ec0a9a75232cad458027ca83437aae3f4da
runc:
Version: 1.2.4
GitCommit: 6c52b3fc541fb26fe8c374d5f58112a0a5dbda66
docker-init:
Version: 0.19.0
GitCommit: de40ad0
[pid 9762] +++ exited with 0 +++
[pid 9764] +++ exited with 0 +++
[pid 9763] +++ exited with 0 +++
[pid 9760] +++ exited with 0 +++
[pid 9761] +++ exited with 0 +++
+++ exited with 0 +++
[pid 9759] connect(3, {sa_family=AF_UNIX, sun_path="/var/run/docker.sock"}, 23) = 0
/var/run/docker.sockに接続して、docker psの結果を出力しています。
dockerコマンドの実態
docker cliはUNIXドメインソケットへのリクエストの詳細を確認してみます。
socketへのHTTPリクエスト
socketへのリクエストはHTTPリクエストが行われています。
実際にシステムコールを通して確認してみます。
sh-4.2$ sudo strace -f -e trace=read,write,connect -s 4096 docker version 2>&1 | grep -E 'GET|POST|HEAD|PUT|DELETE|HTTP/1\.[01]'
[pid 9781] write(3, "HEAD /_ping HTTP/1.1\r\nHost: api.moby.localhost\r\nUser-Agent: Docker-Client/25.0.8 (linux)\r\n\r\n", 92) = 92
[pid 9781] read(3, "HTTP/1.1 200 OK\r\nApi-Version: 1.44\r\nBuilder-Version: 2\r\nCache-Control: no-cache, no-store, must-revalidate\r\nContent-Length: 0\r\nContent-Type: text/plain; charset=utf-8\r\nDocker-Experimental: false\r\nOstype: linux\r\nPragma: no-cache\r\nServer: Docker/25.0.8 (linux)\r\nSwarm: inactive\r\nDate: Sat, 07 Jun 2025 05:04:14 GMT\r\n\r\n", 4096) = 316
[pid 9781] write(3, "GET /v1.44/version HTTP/1.1\r\nHost: api.moby.localhost\r\nUser-Agent: Docker-Client/25.0.8 (linux)\r\n\r\n", 99) = 99
[pid 9781] read(3, "HTTP/1.1 200 OK\r\nApi-Version: 1.44\r\nContent-Type: application/json\r\nDocker-Experimental: false\r\nOstype: linux\r\nServer: Docker/25.0.8 (linux)\r\nDate: Sat, 07 Jun 2025 05:04:14 GMT\r\nContent-Length: 844\r\n\r\n{\"Platform\":{\"Name\":\"\"},\"Components\":[{\"Name\":\"Engine\",\"Version\":\"25.0.8\",\"Details\":{\"ApiVersion\":\"1.44\",\"Arch\":\"amd64\",\"BuildTime\":\"2025-05-16T16:25:56.000000000+00:00\",\"Experimental\":\"false\",\"GitCommit\":\"71907ca\",\"GoVersion\":\"go1.23.8\",\"KernelVersion\":\"5.10.220-209.869.amzn2.x86_64\",\"MinAPIVersion\":\"1.24\",\"Os\":\"linux\"}},{\"Name\":\"containerd\",\"Version\":\"1.7.27\",\"Details\":{\"GitCommit\":\"05044ec0a9a75232cad458027ca83437aae3f4da\"}},{\"Name\":\"runc\",\"Version\":\"1.2.4\",\"Details\":{\"GitCommit\":\"6c52b3fc541fb26fe8c374d5f58112a0a5dbda66\"}},{\"Name\":\"docker-init\",\"Version\":\"0.19.0\",\"Details\":{\"GitCommit\":\"de40ad0\"}}],\"Version\":\"25.0.8\",\"ApiVersion\":\"1.44\",\"MinAPIVersion\":\"1.24\",\"GitCommit\":\"71907ca\",\"GoVersion\":\"go1.23.8\",\"Os\":\"linux\",\"Arch\":\"amd64\",\"KernelVersion\":\"5.10.220-209.869.amzn2.x86_64\",\"BuildTime\":\"2025-05-16T16:25:56.000000000+00:00\"}\n", 4096) = 1046
write(3, "GET /v1.44/version HTTP/1.1\r\nHost: api.moby.localhost\r\nUser-Agent: Docker-Client/25.0.8 (linux)\r\n\r\n", 99) = 99
ポイントはこちらです。
GET /v1.44/version HTTP/1.1 というGETリクエストを行っています。
つまり、socketのpathに対してHTTPリクエストを行っています。
dockerコマンドを介さずにsocket通信
docker cliを介さずにsocketに対して、リクエストをしてみたいと思います。
path: /var/run/docker.sock
request: v1.44/version
sh-4.2$ sudo curl --unix-socket /var/run/docker.sock http://localhost/v1.44/version
{"Platform":{"Name":""},"Components":[{"Name":"Engine","Version":"25.0.8","Details":{"ApiVersion":"1.44","Arch":"amd64","BuildTime":"2025-05-16T16:25:56.000000000+00:00","Experimental":"false","GitCommit":"71907ca","GoVersion":"go1.23.8","KernelVersion":"5.10.220-209.869.amzn2.x86_64","MinAPIVersion":"1.24","Os":"linux"}},{"Name":"containerd","Version":"1.7.27","Details":{"GitCommit":"05044ec0a9a75232cad458027ca83437aae3f4da"}},{"Name":"runc","Version":"1.2.4","Details":{"GitCommit":"6c52b3fc541fb26fe8c374d5f58112a0a5dbda66"}},{"Name":"docker-init","Version":"0.19.0","Details":{"GitCommit":"de40ad0"}}],"Version":"25.0.8","ApiVersion":"1.44","MinAPIVersion":"1.24","GitCommit":"71907ca","GoVersion":"go1.23.8","Os":"linux","Arch":"amd64","KernelVersion":"5.10.220-209.869.amzn2.x86_64","BuildTime":"2025-05-16T16:25:56.000000000+00:00"}
docker versionと同等の結果が返ってきました。
socketへのリクエストは誰が捌いているのか
ソケットファイルに対してリッスンしているプロセスを確認します。
dockerdが待機していることが分かります。dockerdがソケットに来たリクエストを捌きます。
sudo lsof -U | grep docker.sock
systemd 1 root 80u unix 0xffff9ba943a3a000 0t0 39463 /run/docker.sock
dockerd 9107 root 4u unix 0xffff9ba943a3a000 0t0 39463 /run/docker.sock
Discussion