Docker 的一些笔记
一些概念
容器
以下是 Docker Resources 在 what-container 中对容器的介绍:
Containers are an abstraction at the app layer that packages code and dependencies together. Multiple containers can run on the same machine and share the OS kernel with other containers, each running as isolated processes in user space. Containers take up less space than VMs (container images are typically tens of MBs in size), can handle more applications and require fewer VMs and Operating systems.
参考翻译:
容器是在应用层的一种抽象,它将代码和依赖项打包在一起。多个容器可以在同一台机器上运行,并与其他容器共享操作系统内核,每个容器在用户空间中作为独立的进程运行。容器比虚拟机占用更少的空间(容器镜像通常只有几十兆字节大小),可以处理更多的应用程序,并且需要更少的虚拟机和操作系统。
容器的可写层默认不适合长期保存数据。当容器被删除后,写入容器可写层的数据也会随之丢失,因此生产环境通常使用 Volume(数据卷)或 Bind Mount(绑定挂载)实现持久化存储[1]。
镜像
镜像(Image)是容器运行所需文件系统和元数据的只读模板。镜像通过分层存储(Layer)构建,容器启动时会在镜像之上增加一个可写层。可以简单理解为:镜像类似于程序安装包,容器类似于运行中的进程。
仓库
1 | |
一些命令
docker run <options> <image> <command> 是运行一个容器的命令,<options> 是一些选项,<image> 是要运行的镜像,<command> 是要在容器中运行的命令。
关于 <options> 的一些选项:
-d/--detach:后台运行容器-e/--env:设置环境变量--rm:容器停止后自动删除
docker attach:连接到容器主进程的标准输入、标准输出和标准错误流。日常进入容器进行调试时,通常更推荐使用 docker exec -it,因为 docker attach 退出时可能导致容器主进程终止。如果确实使用了 docker attach,需要按 Ctrl+P 然后 Ctrl+Q 来安全退出而不停止容器。
docker stop:停止一个正在运行的容器。
docker start:启动一个已经停止的容器。
docker rm:删除一个已经停止的容器。
docker rmi:删除一个镜像。
docker images:列出本地镜像。
docker ps:列出正在运行的容器。
docker ps -a:列出所有容器(包括已停止的容器)。
docker logs:查看容器日志。
docker exec:在正在运行的容器中执行命令。
docker build .:从 Dockerfile 构建镜像。末尾的 . 是构建上下文(Build Context)的路径——Docker 会把该目录下的所有文件打包发给 Docker Daemon,COPY 和 ADD 只能引用这个范围内的文件,无法访问上下文之外的路径。
docker build -t <image_name> .:从当前目录的 Dockerfile 构建镜像,指定镜像名称。docker build -f <Dockerfile_path> -t <image_name> .:从指定路径的 Dockerfile 构建镜像,指定镜像名称。docker build --build-arg <key>=<value> -t <image_name> .:从当前目录的 Dockerfile 构建镜像,指定构建参数和镜像名称。docker build --no-cache -t <image_name> .:从当前目录的 Dockerfile 构建镜像,指定不使用缓存和镜像名称。
docker cp:在容器和宿主之间复制文件(不支持容器到容器的直接复制)。
docker cp <container_id>:<source_path> <destination_path>:从容器复制文件到宿主。docker cp <source_path> <container_id>:<destination_path>:从宿主复制文件到容器。
💡 注意:如果需要容器间传文件,需先从容器 A 复制到宿主机,再从宿主机复制到容器 B;或使用共享的 Volume(数据卷)来交换文件。
命令演示:
1 | |
命令的更多选项可以参考 Docker CLI 参考文档 。
Dockerfile 定制镜像
Dockerfile 是一个文本文件,包含了一系列命令和指令,用于定义一个 Docker 镜像的构建过程。通过编写 Dockerfile,可以定制镜像,安装所需的软件和配置环境。
FROM <base_image>:指定基础镜像,例如 FROM ubuntu:20.04。
RUN <command>:在当前镜像上执行命令。例如,RUN apt-get update && apt-get install -y nginx。
RUN有两种形式:shell 形式和 exec 形式。shell 形式使用/bin/sh -c执行命令,exec 形式直接执行命令,不使用 shell。- 例如:
- shell 形式:
RUN apt-get update && apt-get install -y nginx - exec 形式:
RUN ["apt-get", "update"]和RUN ["apt-get", "install", "-y", "nginx"]
- shell 形式:
- 例如:
COPY <src> <dest>:将文件从主机复制到容器中。
COPY只能复制构建上下文中的文件和目录,不会自动解压压缩包,也不能从 URL 下载内容。- 例如:
COPY ./nginx.conf /etc/nginx/nginx.conf COPY的<src>可以是一个目录,表示复制目录中的所有文件。例如:COPY ./app /app会将./app目录中的所有文件复制到容器的/app目录中。COPY的<dest>可以是一个目录,如果目录不存在会自动创建。例如:COPY ./app /app会将./app目录中的所有文件复制到容器的/app目录中,如果/app目录不存在会自动创建。COPY的<dest>也可以是一个文件,如果文件不存在会自动创建。例如:COPY ./nginx.conf /etc/nginx/nginx.conf会将./nginx.conf文件复制到容器的/etc/nginx/nginx.conf文件中,如果/etc/nginx/nginx.conf文件不存在会自动创建。COPY的<src>可以有多个,例如:COPY ./app1 ./app2 /app/会将./app1和./app2目录中的所有文件复制到容器的/app/目录中。
- 例如:
ADD <src> <dest>:将文件从主机复制到容器中,支持自动解压 tar 压缩文件。虽然 ADD 也曾支持 URL 下载,但官方更推荐使用 RUN curl 或 RUN wget 显式下载文件(更可控、可校验、可利用缓存)。EXPOSE <port>:声明容器将要监听的端口。
EXPOSE只是一个声明,实际的端口映射需要在运行容器时使用-p选项进行配置。例如:EXPOSE 80声明容器将要监听 80 端口,但需要在运行容器时使用docker run -p 80:80 <image>来映射端口。EXPOSE可以声明多个端口,例如:EXPOSE 80 443声明容器将要监听 80 和 443 端口。
CMD <command>:设置容器启动时默认执行的命令。
CMD有三种形式:- shell 形式:
CMD echo "Hello, World!"(通过/bin/sh -c执行) - exec 形式:
CMD ["echo", "Hello, World!"](直接执行,不使用 shell) - 参数形式(作为 ENTRYPOINT 的默认参数):配合
ENTRYPOINT ["nginx"]使用时,CMD ["-g", "daemon off;"]提供默认参数
- shell 形式:
ENTRYPOINT <command>:设置容器启动时默认执行的命令,且不能被 docker run 的命令行参数覆盖(命令行参数会作为参数追加给 ENTRYPOINT)。
💡 CMD 与 ENTRYPOINT 的区别:
CMD定义默认命令/参数,容易被docker run后面的参数覆盖;ENTRYPOINT则固定了容器的启动行为,docker run后面跟的参数会作为输入传递给ENTRYPOINT。二者常组合使用:ENTRYPOINT指定执行程序,CMD提供默认参数。
ENTRYPOINT有两种形式:shell 形式和 exec 形式。shell 形式使用/bin/sh -c执行命令,exec 形式直接执行命令,不使用 shell。- 例如:
- shell 形式:
ENTRYPOINT echo "Hello, World!" - exec 形式:
ENTRYPOINT ["echo", "Hello, World!"]
- shell 形式:
- 例如:
WORKDIR <dir>:设置工作目录。
WORKDIR用于设置容器内的工作目录,后续的命令(如RUN、CMD、ENTRYPOINT)将在该目录下执行。例如:WORKDIR /app设置工作目录为/app。WORKDIR设置的目录在容器内,如果目录不存在会自动创建。WORKDIR可以设置多个,例如:WORKDIR /app和WORKDIR /app/data,后续命令将在/app/data目录下执行。WORKDIR的路径可以是相对路径或绝对路径,如果是相对路径则相对于前一个WORKDIR设置的目录。例如:WORKDIR /app和WORKDIR data,后续命令将在/app/data目录下执行。
Build Context(构建上下文)
需要注意,WORKDIR 与 Docker Build Context 是两个不同概念。
- 构建上下文是指 Docker 构建镜像时可以访问的文件系统范围,通常是
docker build命令所在的目录及其子目录。 - Dockerfile 中的
COPY和ADD命令只能访问构建上下文中的文件,不能访问上下文外的文件。例如,如果docker build命令在/home/user/app目录下执行,那么 Dockerfile 中的COPY和ADD命令只能访问/home/user/app目录及其子目录中的文件,不能访问/home/user/other目录中的文件。
ENV <key>=<value>:设置环境变量。例如:ENV PORT=80 设置环境变量 PORT 的值为 80。
- 有两个形式,但官方已不推荐(Deprecated)使用空格分隔形式,推荐始终使用
ENV <key>=<value>,以防包含空格的值引起解析错误。例如:ENV PORT=80和ENV PORT 80目前都可用,但应优先使用前者。 ENV设置的环境变量在容器运行时可用,可以通过echo $PORT来查看环境变量的值。- 这里的端口是一个环境变量,不是实际的端口映射。要映射端口需要使用
EXPOSE和docker run -p选项。EXPOSE声明容器将要监听的端口,例如:EXPOSE 80声明容器将要监听 80 端口。docker run -p 80:80 <image>映射容器的 80 端口到宿主的 80 端口。
- 这里的端口是一个环境变量,不是实际的端口映射。要映射端口需要使用
数据管理
Volume(数据卷)
Volume 由 Docker 管理,存储在宿主文件系统的特定目录下(如 /var/lib/docker/volumes/),是持久化数据的推荐方式。
1 | |
Bind Mount(绑定挂载)
Bind Mount 将宿主上的任意目录或文件挂载到容器中,路径由用户自行指定。
1 | |
Volume vs Bind Mount 的区别:
| 特性 | Volume | Bind Mount |
|---|---|---|
| 管理方 | Docker 管理 | 用户自行管理 |
| 路径 | Docker 存储目录 | 用户指定宿主路径 |
| 可移植性 | 好 | 依赖宿主目录结构 |
网络
Docker 网络用于容器间通信以及容器与外部网络的连接。
1 | |
Docker Compose
Docker Compose 用于定义和运行多容器应用,通过 compose.yaml 描述多个服务之间的关系。
1 | |
参考链接
- 酒井科协署培 2025 Docker 讲义
- Docker Resources: what-container
- Docker CLI 参考文档
- Dockerfile 参考文档
- Docker compose 参考文档