16. docker stats统计信息
环境中有一个名为nginx的容器运行。你可以通过以下方法找到容器的统计信息:
$ docker stats nginx CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 048931bbead9 nginx 0.12% 17.21MiB / 737.6MiB 2.33% 7.73kB / 484B 0B / 16.4kB 17
这将启动一个终端窗口,该窗口使用来自容器的实时数据来刷新自身。如果需要退出,请使用CTRL+C停止正在运行的进程。
内置的Docker允许你提供多个名称/id,并在一个窗口中显示它们的统计信息。
环境现在有三个连接的容器在运行。要查看所有这些容器的统计信息,可以使用管道和xargs。管道将一个命令的输出传递到另一个命令的输入,而xargs允许您将该输入作为参数提供给命令。
通过结合这两种方法,我们可以获取由docker ps提供的所有正在运行的容器的列表,并将它们用作docker stats的参数。这让我们对整个机器的容器有了一个概述。
$ docker ps -q | xargs docker stats
17. dockerfile多阶段构建创建优化docker镜像
多阶段特性允许一个Dockerfile包含多个阶段,以生成所需的、优化的Docker映像。
在此之前,这个问题是通过两个dockerfile解决的。一个文件将包含使用开发容器构建二进制文件和工件的步骤,第二个文件将针对生产进行优化,不包括开发工具。
通过在生产映像中删除开发工具,可以重新生成攻击面并改进部署时间。
首先部署一个示例Golang HTTP服务器。目前使用的是两阶段的Docker构建方法。这个场景将创建一个新的Dockerfile,允许使用单个命令构建映像。
git clone https://github.com/katacoda/golang-http-server.git
使用编辑器,创建一个多阶段Dockerfile
。第一阶段使用Golang SDK
构建二进制文件。第二阶段将生成的二进制文件复制到一个优化的Docker镜像中。
# First Stage FROM golang:1.6-alpine RUN mkdir /app ADD . /app/ WORKDIR /app RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . # Second Stage FROM alpine EXPOSE 80 CMD ["/app"] # Copy from first stage COPY --from=0 /app/main /app
目前有一些关于改进语法的讨论,您可以参阅https://github.com/docker/docker/pull/31257
Dockerfile的新语法到位后,构建过程与前面相同。使用下面的build命令创建所需的Docker镜像。
docker build -f Dockerfile.multi -t golang-app .
结果将是两个镜像。一个是第一阶段使用的未标记的镜像,另一个是较小的镜像,也是我们的目标镜像。
如果你收到错误,COPY --from=0 /build/out /app/ Unknown flag: from,这意味着你正在运行一个没有多阶段支持的旧版本的Docker。本场景的步骤1升级当前Docker版本。
可以启动和部署镜像,而不需要进行任何更改。
$docker run -d -p 80:80 golang-app $ curl localhost <h1>This request was processed by host: 178cf19ec6e9</h1>
18. docker ps输出格式
$ docker run -d redis $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1bf198e56506 redis "docker-entrypoint.s…" 22 seconds ago Up 18 seconds 6379/tcp angry_northcutt # --format方法 $ docker ps --format '{{.Names}} container is using {{.Image}} image' angry_northcutt container is using redis image $ docker ps --format 'table {{.Names}}\t{{.Image}}' NAMES IMAGE angry_northcutt redis
然而,format参数允许显示通过docker ps命令已经暴露的数据。如果您想包含额外的信息,比如容器的IP地址,那么数据需要通过docker inspect
来获取。然后,format参数可以访问所有容器信息。下面是列出正在运行的容器的所有IP地址的示例。
$ docker ps -q | xargs docker inspect --format '{{ .Id }} - {{ .Name }} - {{ .NetworkSettings.IPAddress }}' 1bf198e565063b29b75341cf958536482d2e6ad605a8032d0572e2b1770ab924 - /angry_northcutt - 172.18.0.2
19. Docker非root特权配置
该环境当前运行的是Ubuntu 16.04,用户以root身份登录。第一步是创建一个没有这些root特权的新用户,这意味着他们将以更高的安全性运行,并且不能对系统进行关键更改。
useradd
命令将创建一个具有默认权限的用户。在终端上执行命令,添加一个名为lowprivuser
的新用户。这个用户可以被称为任何名称。
$ useradd -m -d /home/lowprivuser -p $(openssl passwd -1 password) lowprivuser
使用’sudo su
',可以切换到以这个新的低权限用户运行。
$ sudo su lowprivuser lowprivuser@host01:/root$
当作为该用户运行时,一些项会发生变化。例如,用户无法在某些位置(如根目录)创建或更改文件,
lowprivuser@host01:/root$ touch /root/blocked touch: cannot touch '/root/blocked': Permission denied
户也无法访问Docker,因为之前这需要他们有根权限。
lowprivuser@host01:/root$ docker ps Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.40/containers/json: dial unix /var/run/docker.sock: connect: permission denied
在下一步中,我们将部署新的Rootless
版本,并允许用户启动自己的容器。Docker提供了一个脚本,用于部署新的Rootless
版本所需的组件。
使用lowprivuser
命令执行脚本,安装组件。
lowprivuser@host01:/root$ curl -sSL https://get.docker.com/rootless | sh # Installing stable version 20.10.8 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 58.1M 100 58.1M 0 0 55.4M 0 0:00:01 0:00:01 --:--:-- 55.5M % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 18.0M 100 18.0M 0 0 35.2M 0 --:--:-- --:--:-- --:--:-- 35.2M + PATH=/home/lowprivuser/bin:/root/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games /home/lowprivuser/bin/dockerd-rootless-setuptool.sh install [INFO] systemd not detected, dockerd-rootless.sh needs to be started manually: PATH=/home/lowprivuser/bin:/sbin:/usr/sbin:$PATH dockerd-rootless.sh [INFO] Creating CLI context "rootless" Successfully created context "rootless" [INFO] Make sure the following environment variables are set (or add them to ~/.bashrc): # WARNING: systemd not found. You have to remove XDG_RUNTIME_DIR manually on every logout. export XDG_RUNTIME_DIR=/home/lowprivuser/.docker/run export PATH=/home/lowprivuser/bin:$PATH export DOCKER_HOST=unix:///home/lowprivuser/.docker/run/docker.sock
完成这一步之后,继续下一步,设置用户环境并开始启动容器。
现在已经安装了 rootless Docker
。可以使用以下脚本启动守护进程:
export XDG_RUNTIME_DIR=/tmp/docker-1001 export PATH=/home/lowprivuser/bin:$PATH export DOCKER_HOST=unix:///tmp/docker-1001/docker.sock mkdir -p $XDG_RUNTIME_DIR /home/lowprivuser/bin/dockerd-rootless.sh --experimental --storage-driver vfs
这将在前台运行,并允许您查看来自rootless Docker守护进程的调试输出。
单击以下命令启动第二个终端窗口,以lowprivuser用户登录
sudo lowprivuser
要访问Docker,请设置以下环境变量。它指定了对id为1001的用户运行的Docker实例的连接,该连接应该与lowprivuser的id匹配。
export XDG_RUNTIME_DIR=/tmp/docker-1001 export PATH=/home/lowprivuser/bin:$PATH export DOCKER_HOST=unix:///tmp/docker-1001/docker.sock
在下一步中,我们可以启动容器。
现在可以访问用户1001
运行的Docker守护进程。
标准的Docker CLI命令的工作方式与此相同。下面的命令列出了为用户运行的所有容器,目前它应该返回一个空列表。
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
可以查看Daemon运行的细节:
docker info docker run -it ubuntu bash root@002495da35fe:/# id uid=0(root) gid=0(root) groups=0(root)
容器内的用户仍然被报告为root。他们将能够安装包和修改Docker内部运行的部分系统。然而,如果它们设法逃脱,它们将无法干扰宿主。
在单独的终端窗口中,宿主机root用户可以查看哪些进程正在运行,哪些用户启动了它们。使用ps aux可以验证我们的新容器实例是由低特权用户管理和拥有的。
$ id; ps aux | grep lowprivuser uid=0(root) gid=0(root) groups=0(root) root 21016 0.0 0.2 52700 3940 pts/0 S 03:18 0:00 sudo su lowprivuser root 21017 0.0 0.2 52280 3540 pts/0 S 03:18 0:00 su lowprivuser lowpriv+ 21145 0.0 0.4 710816 6912 pts/0 Sl+ 03:22 0:00 rootlesskit --net=vpnkit --mtu=1500 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run --propagation=rslave /home/lowprivuser/bin/dockerd-rootless.sh --experimental --storage-driver vfs lowpriv+ 21150 0.5 0.7 711712 12228 pts/0 Sl+ 03:22 0:01 /proc/self/exe --net=vpnkit --mtu=1500 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run --propagation=rslave /home/lowprivuser/bin/dockerd-rootless.sh --experimental --storage-driver vfs lowpriv+ 21430 0.0 0.5 711432 8612 ? Sl 03:26 0:00 /home/lowprivuser/bin/containerd-shim-runc-v2 -namespace moby -id 002495da35fe1431fd79e2dda1bf3447c7d4d9890220067324c9d64aa0f30e9f -address /tmp/docker-1001/docker/containerd/containerd.sock root 21532 0.0 0.0 14224 920 pts/2 S+ 03:27 0:00 grep --color=auto lowprivuser
系统现在运行Docker容器,不需要任何额外的权限,允许我们的系统以更高的安全性操作。
相关阅读: