1. 概述

本文我们将学习如何在Docker容器中使用不同的用户执行命令。

首先我们使用root用户访问Docker容器,以获取最高权限,然后讨论如何为root用户和非root用户设置密码,以保护容器免受攻击。

2. 运行一个示例容器

为了方便演示,我们创建一个Dockerfile。Docker容器默认以root用户运行,为了安全考虑限制用户权限,这里添加一个用户john,并将其作为默认用户:

FROM ubuntu:16.04
RUN apt-get update 
RUN useradd -m john
USER john
CMD /bin/bash

这里我们使用 ubuntu:16.04 作为基础镜像,下面使用 docker build 命令来构建镜像

$ docker build -t baeldung .
Sending build context to Docker daemon  2.048kB
Step 1/5 : FROM ubuntu:16.04
16.04: Pulling from library/ubuntu
58690f9b18fc: Pull complete 
...
Step 5/5 : CMD /bin/bash
 ---> Running in d04af94585e2
Removing intermediate container d04af94585e2
 ---> 312faa93c781
Successfully built 312faa93c781
Successfully tagged baeldung:latest

现在,使用我们新构建的 baeldung 镜像来运行一个Docker容器:

$ docker run -id --name baeldung baeldung
34dbc77279a2a6244b0e4ee87890d79e814128391c6a4387d2e2fd10fa6e8f20

使用 docker ps 命令检查容器是否正在运行:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS               NAMES
34dbc77279a2        baeldung            "/bin/sh -c /bin/bash"   About a minute ago   Up About a minute                       baeldung

3. 访问Docker容器

3.1. 使用非root用户

使用 docker exec 命令我们可以进入正在运行的容器里:

$ docker exec -it baeldung bash

记得前面我们创建的Dockerfile中,我们添加了一个名为 john 的用户,它被设置为运行容器时的默认用户。我们可以使用whoami命令来验证这一点:

$ whoami
john

因为是非root运行,所以如果安装任何软件,会报错:

$ apt-get update
Reading package lists... Done
W: chmod 0700 of directory /var/lib/apt/lists/partial failed - SetupAPTPartialDirectory (1: Operation not permitted)
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
E: Unable to lock directory /var/lib/apt/lists/

现在,我们退出容器,下面学习使用root用户重新登录。

3.2. 使用 root 用户

我们可以通过 -u 参数 指定进入容器时使用的用户:

$ docker exec -it -u 0 baeldung bash

上面的 -u 0 为 root 用户的ID,我们也可以使用用户名:

$ docker exec -it -u root baeldung bash

执行whoami命令确认当前用户信息:

$ whoami
root

现在,我们以root用户身份进入了容器。我们可以在容器上执行任何操作。

另一种方案,我们也可以 nsenter 命令。首先我们需要知道正在运行的容器的PID,获取命令如下:

$ docker inspect --format {{.State.Pid}} baeldung
6491

得到 PID 后,执行 nsenter 命令:

$ nsenter --target 6491 --mount --uts --ipc --net --pid

这使我们可以作为root用户访问Docker容器,并执行任何操作。

4. 在容器内使用 sudo 命令

将前面的 Dockerfile 稍加修改,安装下 sudo

FROM ubuntu:16.04
RUN apt-get update && apt-get -y install sudo
RUN useradd -m john && echo "john:john" | chpasswd && adduser john sudo
USER john
CMD /bin/bash

我们还使用了 chpasswd 命令为 john 用户添加密码,然后将其作为默认用户。

然后构建镜像:

$ docker build -t baeldung .

运行容器:

$ docker run -id --name baeldung baeldung
b0f83a7e8b49ddf043c80792f21d5c483c0c5ab56c700815a83b0a40e5292754

进入容器:

$ docker exec -it baeldung bash
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

检测当前登录的用户名

$ whoami
john

这确认了我们以非root用户的身份登录。如果我们运行 apt-get update 命令,我们将遇到与3.2节相同的权限相关问题。

这次,我们将使用 sudo 命令为非root用户 john 获取特权:

$ sudo apt-get update
[sudo] password for john: 
Get:1 http://security.ubuntu.com/ubuntu xenial-security InRelease [99.8 kB]
Hit:2 http://archive.ubuntu.com/ubuntu xenial InRelease 
Get:3 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [99.8 kB]
Get:4 http://archive.ubuntu.com/ubuntu xenial-backports InRelease [97.4 kB]
Fetched 297 kB in 1s (178 kB/s)
Reading package lists... Done

然后操作成功了

5. 总结

在本文中,我们展示了如何在Docker容器中使用不同用户运行命令。首先,我们讨论了在运行的Docker容器中root用户和非root用户的角色。然后,我们学习了如何作为root用户访问Docker容器以获取额外的特权。

理想情况下,我们不应该允许root用户访问Docker容器。这增加了更多的安全顾虑。相反,我们应该创建一个单独的用户来访问容器。这是在容器世界中的标准安全步骤。