Docker 是一个仍然依赖主机内核、CPU ISA 及其 x86-64 syscall 的容器系统。
在 Docker 容器中运行的应用称为容器化应用。
组件概览 #
Docker Engine:dockerd
#
dockerd 是一个 CLI 守护进程,用于管理本地系统中安装的容器。
它以 Docker Engine 或 Docker CE(社区版)为产品名称,并且开源、免费。
dockerd 守护进程在 UNIX 域套接字 /var/run/docker.sock 上侦听传入的客户端连接。
运行 Docker 客户端的用户必须拥有此套接字文件的读取权限,才能建立套接字连接(以发送 HTTP 请求)。
如果通过 Linux 发行版的包管理器安装 Docker Engine,此套接字文件可能只允许 root 或
Docker 专用用户组(例如 docker)读取。
可以选择将自己加入该用户组,也可以直接切换为 root 后再使用 docker 客户端。
使用 docker info 检查 dockerd 是否正在运行,以及客户端是否拥有相应权限。
dockerd 守护进程公开用于管理容器的 HTTP API,任何程序均可调用。
官方客户端程序是 docker CLI。
Docker Desktop #
Docker Desktop 是专有的 GUI 客户端程序,它与 dockerd 通信并执行容器的日常管理。
并非必须使用 Docker Desktop 应用。
Docker Compose #
https://docs.docker.com/compose/
Docker Compose 是另一个与 dockerd 通信的 CLI 客户端,其可执行文件为 docker-compose。
它使用 docker-compose.yml 文件指定容器属性,而不必到处键入 docker run 选项。
该工具适合配置反复使用和/或配置复杂的服务。
镜像 #
Docker 镜像由多层文件系统内容组成,每一层都在前一层之上添加一些文件。 如果某个镜像的第一层依赖另一个镜像的全部层,则称该镜像基于另一个镜像。
镜像具有人类可读的名称 REPOSITORY 和人类可读的 TAG(通常是版本号,但并非强制要求)。
称为 IMAGE ID 的 SHA256 哈希可唯一标识镜像。
要构建自己的镜像,需要创建一个 Dockerfile,并使用简单语法定义创建镜像所需的步骤。
Dockerfile 中的每条指令都会在镜像中创建一层。
修改 Dockerfile 并重新构建镜像时,仅重新构建发生变化的层。
例如,esolang/vim:latest 镜像包含 10 层。
# $ Docker Pull Esolang/vim
Using default tag: latest
latest: Pulling from esolang/vim
4abcf2066143: Downloading 2.951MB/3.409MB
e7609a7fad9e: Download complete
a891a2921638: Download complete
6ea6322cdcb0: Download complete
729f825b6ae6: Download complete
e6cb43f5f474: Downloading 2.618MB/31.24MB
c12ed1c2e19b: Download complete
6928286dd6f6: Download complete
05de04103836: Download complete
b5a8264627eb: Download completeDocker 不会在构建后的镜像中存储 Dockerfile,因此检查镜像的构建方式会稍显困难。
原因在于,也可以通过运行容器、进行修改并提交结果来创建镜像。
实际上,可以将 Dockerfile 视为自动执行“运行—修改—提交”过程的脚本。
最小镜像 #
构建一个没有基础镜像且没有文件系统内容的最小 Docker 镜像(其中仅包含一个最小的 hello world 可执行文件):
; linux_syscall call_no, arg0, arg1, arg2, arg3, arg4, arg5
%macro linux_syscall 1-7 0,0,0,0,0,0
mov rax, %1
mov rdi, %2
mov rsi, %3
mov rdx, %4
mov r10, %5
mov r8, %6
mov r9, %7
syscall
%endmacro
SECTION .data
msg: db `hello world\n`
msglen: equ $-msg
GLOBAL main
SECTION .text
main:
; write to stdout a string
linux_syscall 1,1,msg,msglen
; exit the process with code 42
linux_syscall 0x3c, 42使用 make 构建可执行文件:
main: main.o
# -N: don't align data segment on a new memory page, thus makes the executable as small as possible
ld -N -e manbaout -omain main.o
main.o: main.asm
nasm -f elf64 -o main.o main.asm
clean:
rm *.o main
使用以下 Dockerfile 构建镜像:
FROM scratch
ADD main /docker build -t foo .在我的计算机上,这会生成一个只有 904 字节的 Docker 镜像(由 docker image ls 报告)。从该镜像运行容器:
docker run foo ./main容器 #
容器是镜像的运行实例。容器的生命周期从 docker container create <image> 命令开始,随后执行 docker start <container>。docker run <image> 是同时完成这两步的快捷方式;如果本地不存在 <image>,它还会从已配置的注册表(默认为 Docker Hub)下载镜像。docker run 始终基于给定镜像创建一个全新容器并启动它。
要使用已有但未运行(已退出或已暂停)的容器,请再次使用 docker start。
在任意时刻,Docker 容器会处于以下 6 种状态之一。
- created:完好;容器自创建以来从未启动。
- running:ENTRYPOINT 进程正在运行(准确地说,对它执行
wait(2)会阻塞) - Restarting:
- Exited(num):ENTRYPOINT 进程以 num 退出。
- Paused:
- Dead:
Dockerfile #
Dockerfile 仅定义了 17 条指令:
| 名称 | |
|---|---|
| ADD | 添加本地或远程文件及目录。 |
| ARG | 使用构建时变量。 |
| CMD | 指定默认命令。 |
| COPY | 复制文件和目录。 |
| ENTRYPOINT | 指定默认可执行文件。 |
| ENV | 设置环境变量。 |
| EXPOSE | 描述应用正在侦听的端口。 |
| FROM | 从基础镜像创建新的构建阶段。 |
| HEALTHCHECK | 在启动时检查容器的健康状态。 |
| LABEL | 向镜像添加元数据。 |
| MAINTAINER | 指定镜像作者。 |
| ONBUILD | 指定镜像用于构建时执行的指令。 |
| RUN | 执行构建命令。 |
| SHELL | 设置镜像的默认 shell。 |
| STOPSIGNAL | 指定退出容器所用的系统调用信号。 |
| USER | 设置用户和组 ID。 |
| VOLUME | 创建卷挂载。 |
| WORKDIR | 更改工作目录。 |
只有 RUN、COPY 和 ADD 指令会创建保留在最终镜像中的层。
多数指令规定 docker image build 命令应如何在最终的静态镜像中添加新层。
RUN命令是一个例外,它会在构建时立即执行外部命令。
区分在 docker image build 运行时立即执行的指令,以及规定从所创建镜像实例化容器后 Docker 应如何操作的指令,至关重要。
CLI 速查表 #
# Show Active Container
docker container ls
# Show All Container Includes Dead One
docker container ls -a
# Stop Certain Containers
docker stop <cid1> <cid2> ...
# Stop All Active Containers
docker stop $(docker container ls –aq)
评论
在 GitHub 上阅读或评论(发表评论需要登录)