Docker 简明教程
Docker - Containers & Shells
在 Docker 容器中,Shell 必不可少;它们充当界面,通过它们可以在容器中执行命令。通常,当一个容器启动时,它必须运行一个 shell 来解释和执行 Dockerfile 中描述的命令或在运行容器时传递的命令。
Shells are essential in Docker containers; they act as interfaces through which the execution of commands in the container occurs. Usually, when a container is started, it has to run a shell to interpret and execute the commands either described in the Dockerfile or passed when the container is run.
Shell 执行以下几项至关重要的功能 −
The shell performs several vital functions −
-
Command Execution − Shells interpret and execute commands authored in scripts or entered interactively by users. This includes software installation, environment configuration, and application execution.
-
Script Automation − One of the biggest roles shell scripts play in Dockerfiles is the automation of the container environment setup. It ensures that all essential steps are automatically and consistently executed.
-
Interactive Access − Shells enable interactive access to containers, allowing developers and admins to debug, manage, and examine the container’s environment. This is done interactively by running commands, for instance, docker exec, against a running container to have a shell session opened inside it.
Types of Shells Commonly Used in Docker
在 Docker 容器中使用着相当多的 Shell 类型,它们都具有不同的特性和优势 −
There are quite a few types of shells being used in Docker containers with different features and advantages −
Bash (Bourne Again Shell)
-
Default Shell − Bash is the default shell for most Linux distributions and is, by a wide margin, the most used among Docker containers.
-
Scripting − It has extensive scripting, from variables and loops to conditionals and functions.
-
Rich Functionality − Bash provides features such as command history, job control, and tab completion that enhance interactive use.
Sh (Bourne Shell)
-
Simplicity − Sh is a very simple shell compared to Bash. It is the original Unix shell and is available on almost all Unix-like systems.
-
Portability − Sh scripts are highly portable and can run on virtually any Unix-like operating system.
-
Fewer Features − It is not quite as featureful as bash, but that allows scripts to be generally easier to write portably.
Zsh (Z Shell)
-
Advanced Features − It has most of the advanced features that are absent in Bash, like better tab completions, extensive scripting capabilities, and highly customizable prompts.
-
Customization − It is highly customizable, allowing users to tailor the shell environment to their preferences.
-
Popularity − With its powerful features and customization, Zsh has become especially popular among developers.
Accessing Shells with in Docker Containers
让我们了解在 Docker 容器中访问 shell 的不同方法。
Let’s understand the different ways to access shells within Docker Containers.
Docker exec Command (Interactive and Detached Modes)
访问和与正在运行的 Docker 容器进行交互的最佳方法之一是使用 docker exec 命令。它允许在现有容器内启动新进程,从而允许执行命令或甚至打开一个交互式 shell 会话。
One of the best ways of accessing and interacting with running Docker containers is through the docker exec command. It allows for the starting of a new process inside an existing container, hence allowing the execution of commands or even opening an interactive shell session.
docker exec 命令与标志 -it 一起使用,以交互方式访问正在运行的容器中可用的 shell。在这种情况下,-i 表示交互,-t 分配一个伪 TTY。通过这种方式,用户可以与 shell 交互,就像他们真的登录了一样。
The docker exec command is used with the flags -it to access a shell available inside a running container interactively. In this case, -i means interactive, and -t allocates a pseudo-TTY. In this way, a user can interact with a shell as if they were really logged in.
在已经运行的容器内运行 Bash shell 的示例命令 -
Example command to run a Bash shell inside a container that is already running −
$ docker exec -it <container_id> /bin/bash
在上面的示例中,将 <container_id> 替换为实际的正在运行的容器 ID 或名称。这会将用户放到容器内的实时 Bash shell 中进行交互和命令执行。
In the above example, replace <container_id> with the actual running Container ID or Name. This will drop the User into a real-time Bash shell within the Container for interaction and command execution.
除此之外,docker exec 还可以接受以分离方式做事 - 执行命令,但不会将用户连接到进程。这对于容器内的所有后台处理或非交互式命令非常有用。
Besides that, docker exec can also accept the option to do things in a detached way - executing the command but without attaching the user to the process. This is great for all background processing or non-interactive commands within the container.
示例分离进程命令 -
Example detached process command −
$ docker exec -d <container_id> <command>
在此示例中,<command> 是您想在容器内运行的命令,并且由于我们使用了 -d,因此该命令将在后台运行,您的命令行会与该进程分离。
In this example, <command> is the command you want to run inside the container, and since we’ve used -d, the command will be run in the background with your command line detached from the process.
docker run -it (Interactive Terminal at Container Start)
当您想要启动新的容器,并以交互方式在其中打开一个终端会话时,可以使用 docker run -it 命令。这在从创建开始就以交互方式对新容器进行调试、测试或配置时非常实用。
You can use a docker run -it command when you want to initiate a new container and with an interactive way of opening a terminal session within it. This can be very practical when debugging, testing, or configuring new containers interactively from its creation.
使用 Bash 在新容器中启动交互式 shell 的示例命令 -
Example command to launch a new container with an interactive shell in Bash −
$ docker run -it <image_name> /bin/bash
在上面的示例中,在 <image_name> 中,您必须包含希望从中创建容器的 Docker 镜像名称。选项 -it 然后进行交互和伪 TTY 分配模式,允许用户直接与容器进行交互。
In the above example, in <image_name>, you have to include the name of the Docker image you want to be created the container from. The option -it then makes the interactive and pseudo-TTY allocation mode, allowing the user to interact directly with the container.
nsenter and Other Low-Level Tools
nsenter 是低级别的 Linux 实用程序,用于访问正在运行进程的名称空间。Docker 容器使用 Linux 名称空间作为隔离;nsenter 用于进入这些名称空间,从而获得对位于容器内的环境的访问。
nsenter is a low-level Linux utility to access the namespaces of a running process. Docker containers use Linux namespaces as isolation; nsenter is used to enter into these namespaces and thus get access to the environment lying inside the container.
使用 nsenter 输入容器名称空间的示例命令 -
Example command to enter the namespaces of a container using nsenter −
1. 首先,获取在容器中运行的主进程的 PID -
1. First off, get the PID of the main process running in the container −
$ docker inspect --format "{{.State.Pid}}" <container_id>
2. 使用 nsenter 获取对容器名称空间的访问权限 -
2. Use nsenter to gain access to the namespaces of the container −
$ nsenter --target <pid> --mount --uts --ipc --net --pid /bin/bash
在此示例中,用第一步中获得的 PID 替换 <pid>。这将在容器的名称空间中打开一个 bash,并可以完全访问容器的环境。
In this example, replace <pid> with the PID you got in the first step. This will open a bash inside the namespaces of the container with full access to the environment of the container.
Using Docker Desktop with Shell Access(GUI)
Docker Desktop 是针对 macOS 和 Windows 操作系统的一种便利之处,因为它提供了用于处理 Docker 容器的图形用户界面。因此,Docker CLI 中许多可能复杂的工作,例如打开进入容器的 shell,都通过其 GUI 进行了简化。
Docker Desktop is a convenience for the macOS and Windows operating systems in a way that it provides a graphical user interface to work with Docker containers. As a result, much of what may be complex work in Docker CLI, such as opening a shell into a container, is simplified through its GUI.
使用 Docker Desktop 访问 shell -
To access a shell using Docker Desktop −
-
Open Docker Desktop − Start the Docker Desktop application from your applications menu.
-
View Containers − Click the "Containers/Apps" tab to view a running container listing.
-
Open Terminal − Simply click on the container you want to connect to and then click the "CLI" or "Terminal" button. This will open a new terminal window attached to the container, usually with a Bash shell inside.
Running Containers as Non-Root Users
容器以非 root 用户运行是一种必要的安全实践。默认情况下,docker 容器以 root 用户运行。如果攻击者进入容器,这样做将会导致高风险。在容器内以最低必要的权限运行有助于减少潜在的损害。
Containers run as non-root users is a necessary security practice. Docker containers run, by default, as the root user. Doing so would lead to a high level of risk if an attacker gained entrance to the container. Running minimum necessary permissions inside the container helps to reduce potential damage.
Best Practices
Create Non-Root Users - 使用 USER 指令在 Dockerfile 中定义非 root 用户。例如 -
Create Non-Root Users − Define non-root users in your Dockerfile using the USER instruction. For example −
FROM ubuntu:latest
RUN useradd -m nonrootuser
USER nonrootuser
Restrict Capabilities - 通过使用 Docker 的 --cap-drop 和 --cap-add 选项来删除特权,从而限制容器的能力。
Restrict Capabilities − Limit the capabilities of the container by using Docker’s --cap-drop and --cap-add options to drop unnecessary privileges.
File System Permissions - 确保正确设置文件系统权限,以防止对敏感文件和目录进行未经授权的访问。
File System Permissions − Ensure file system permissions are correctly set to prevent unauthorized access to sensitive files and directories.
Conclusion
在本章中,我们讨论了如何访问容器外壳。我们研究了不同类型的容器外壳以及用于访问每一个容器外壳的命令。如果你想检查 docker 容器内部发生的事情,或者你想要在容器中运行命令,这些命令会很有用。
In this chapter, we have discussed how to access container shells. We looked at the different types of shells and the commands to access each of them. These commands are useful if you want to inspect what’s happening inside Docker containers or if you want to run commands in Containers.
FAQs on Docker Containers & Shells
1. What should I do if the docker container doesn’t have a shell?
有时,为了保持小镜像大小,容器镜像特意没有外壳。在这种情况下,你可以执行下列操作:使用安装了外壳的新层提交正在运行的容器,然后基于此修改后的镜像启动新的容器。
Sometimes container images are left without a shell on purpose to keep the image size small. In this case, you can do the following: Commit the running container with a new layer where the shell is installed, and then start a new container based on this modified image.
你可以使用 Docker cp 命令或以其他方式将外壳二进制文件复制到容器中。更高级的方法是使用 nsenter 来相对直接地访问现有容器的名称空间。
You can use the Docker cp command or copy the shell binary to the container in other ways. More advanced is using nsenter to access the existing container’s namespaces relatively directly.
2. Are there any Alternatives to Accessing Docker Container Shells?
是的,除了直接访问之外,还有其他方法可以与容器进行交互。例如,可以通过使用 docker logs 查看容器输出,通过使用 docker inspect 观察容器详情,或者通过使用 docker stats 检查资源使用情况。
Yes, there are other ways to interact with containers besides direct access. For example, one can view container output by making use of docker logs, inspect container details by using docker inspect, or check the resource usage by using docker stats.
具有连接的调试器的 docker exec 等专用工具启用了此类调试可能性,或者当需要深入分析正在运行的进程时通过 strace 和 gdb 启用。最终,最佳方法将基于你的需求以及你的任务需要多少访问权限。
Dedicated tools like docker exec with a debugger attached enable such debugging possibilities or via strace and gdb when there is a necessity for in-depth analysis of running processes. Ultimately, the best approach will be based on your needs and how much access is needed for your task.