平常使用Docker部署应用的时候,为了保障安全、压缩镜像体积和加快编译速度,一般会尽量去除运行时不需要的库和程序,比如sshd,这样带来的一个副作用是当容器出现问题时不容易登录上去调试。Google搜索到了docker-slim项目提供的一种辅助思路,这里大致做笔记记录一下。

环境准备

简单的HTTP Server

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package main

import (
  "log"
  "net/http"
)

func main() {
  err := http.ListenAndServe(":8080", nil)
  if err != nil {
    log.Fatal("Server error: ", err)
  }
}

Dockerfile

1
2
3
4
5
6
7
8
9
FROM golang:1.11 as builder
WORKDIR /
COPY main.go .
RUN CGO_ENABLED=0 GOOS=linux go build -o app .

FROM scratch
EXPOSE 8080
COPY --from=builder /app .
ENTRYPOINT ["/app"]

启动待测试容器

1
docker build -t test -f Dockerfile . && docker run --name test -p 8080:8080 --rm test

Sidecar调试

启动sidecar容器
1
docker run --rm -it --pid=container:test --net=container:test --cap-add sys_admin alpine sh

这里使用Docker Hub里默认的alpine镜像,命令中的test是上面启动的容器名称。

运行后执行ps命令可以看到/app进程,说明已经连上了。

1
2
3
4
5
/ # ps
PID   USER     TIME  COMMAND
    1 root      0:00 /app
   12 root      0:00 sh
   19 root      0:00 ps

开工

/app对应的PID是1,配合系统命令就可以做不少调试工作了,比如列举文件:

1
2
3
4
5
6
7
/ # ls -lh /proc/1/root/
total 6344
-rwxr-xr-x    1 root     root        6.2M Sep 11 09:15 app
drwxr-xr-x    5 root     root         340 Sep 11 09:37 dev
drwxr-xr-x    2 root     root        4.0K Sep 11 09:37 etc
dr-xr-xr-x  229 root     root           0 Sep 11 09:37 proc
dr-xr-xr-x   13 root     root           0 Sep 11 09:37 sys

或者查看监听进程:

1
2
/ # netstat -anp | grep 8080
tcp        0      0 :::8080                 :::*                    LISTEN      1/app

其它有用的命令还有:

1
2
3
4
5
6
cat /proc/<TARGET_PID>/cmdline
ls -l /proc/<TARGET_PID>/cwd
cat /proc/<TARGET_PID>/environ
cat /proc/<TARGET_PID>/limits
cat /proc/<TARGET_PID>/status
ls -l /proc/<TARGET_PID>/fd

参考

History

Version Action Time
1.0 Initial commit Sep 11, 2018