一、容器简介
关注我可获取系统性云计算课程。Docker 容器是一种轻量级的、可移植的、自包含的软件打包技术。它将应用程序及其所有依赖项(包括代码、运行时环境、系统工具、库等)打包到一个称为容器的独立单元中,使得应用可以在任何支持 Docker 的环境中一致地运行。
二、容器的基本操作
(一)运行容器
基本运行命令
使用docker run命令来启动一个新的容器。例如,以下命令启动一个基于ubuntu:latest镜像的容器:
docker run -it ubuntu:latest /bin/bash
这里-it参数表示以交互模式(-i)和分配一个伪终端(-t)运行,/bin/bash是容器启动后执行的命令,让我们可以在容器内获得一个 bash shell。
端口映射
如果容器内的应用需要对外提供服务(如 Web 应用),需要将容器内的端口映射到主机端口。例如,运行一个 Nginx 容器并将容器内的 80 端口映射到主机的 8080 端口:
docker run -d -p 8080:80 nginx
这里-d表示在后台运行容器,-p参数用于指定端口映射。
挂载数据卷
为了在容器和主机之间共享数据或者持久化容器内的数据,可以使用数据卷挂载。例如,将主机的/data目录挂载到容器内的/app/data目录:
docker run -v /data:/app/data myimage
(二)查看容器
查看正在运行的容器
使用docker ps命令可以列出当前正在运行的容器。它会显示容器的 ID、镜像名称、创建时间、状态等信息。例如:
docker ps
查看所有容器(包括已停止的)
使用docker ps -a命令可以查看所有的容器,无论其是否正在运行。这对于查看已经退出的容器状态或者重新启动容器很有用。
(三)停止和启动容器
停止容器
使用docker stop命令来停止一个正在运行的容器。可以通过容器的 ID 或者名称来指定要停止的容器。例如:
docker stop mycontainer
启动已停止的容器
使用docker start命令来启动一个已经停止的容器。例如:
docker start mycontainer
(四)删除容器
删除单个容器
使用docker rm命令来删除一个已经停止的容器。例如:
docker rm mycontainer
如果容器正在运行,需要先停止它才能删除。可以使用-f参数强制删除正在运行的容器,但这可能会导致数据丢失或其他问题,应谨慎使用。
2. 删除所有已停止的容器
可以使用以下命令删除所有已经停止的容器:
docker container prune
三、容器的生命周期管理
(一)创建容器
当执行docker run命令时,Docker 会首先检查本地是否存在指定的镜像,如果不存在,会从远程仓库下载。然后,Docker 会根据镜像创建一个新的容器,并执行指定的启动命令。
(二)运行中的容器维护
监控容器资源使用
可以使用docker stats命令来实时监控容器的资源使用情况,包括 CPU 使用率、内存使用量、网络 I/O 等信息。例如:
docker stats mycontainer
在运行的容器内执行命令
使用docker exec命令可以在一个正在运行的容器内执行命令。例如,在一个运行中的 Ubuntu 容器内执行ls命令:
docker exec mycontainer ls
(三)容器的停止和销毁
当容器内的主进程结束或者接收到docker stop命令时,容器会停止运行。停止后的容器可以重新启动,也可以使用docker rm命令将其删除,释放资源。
四、容器的网络配置
默认网络模式
Docker 有几种默认的网络模式,其中bridge是最常用的一种。在bridge模式下,Docker 会创建一个虚拟网桥,每个容器都连接到这个桥上,并分配一个内部 IP 地址。容器之间可以通过这些内部 IP 地址相互通信,并且可以通过端口映射将容器内的服务暴露到主机上。
自定义网络
可以使用docker network create命令创建自定义网络。例如:
docker network create mynetwork
然后,可以在运行容器时将容器连接到这个自定义网络中:
docker run --network=mynetwork myimage
自定义网络提供了更好的网络隔离和配置灵活性,可以方便地实现容器之间的复杂网络连接。
五、容器的资源限制
内存限制
可以使用-m或--memory参数来限制容器可以使用的内存大小。例如,限制容器使用 512MB 内存:
docker run -m 512m myimage
CPU 限制
使用--cpus参数可以限制容器可以使用的 CPU 核心数。例如,限制容器使用 1.5 个 CPU 核心:
docker run --cpus=1.5 myimage
资源限制可以确保在同一主机上运行的多个容器之间合理分配资源,避免某个容器过度占用资源而影响其他容器的运行。
六、容器的安全机制
内核命名空间(Namespace)
Docker 利用内核命名空间来实现容器之间的隔离。包括 PID 命名空间(进程 ID 隔离)、网络命名空间(网络隔离)、挂载命名空间(文件系统挂载点隔离)等。例如,不同容器中的进程在 PID 命名空间中具有独立的进程 ID,使得它们在各自的容器内看起来像是独立的系统。
控制组(CGroup)
CGroup 用于限制和隔离容器对资源的使用。通过 CGroup,可以对容器的 CPU、内存、磁盘 I/O 等资源进行配额和限制,保证资源的合理分配和系统的稳定性。
七、容器的日志管理
查看容器日志
使用docker logs命令可以查看容器的日志信息。例如:
docker logs mycontainer
可以添加-f参数来实时跟踪日志输出,类似于tail -f命令的效果。
2. 日志驱动配置
Docker 允许配置不同的日志驱动,如json - file(默认)、syslog、journald等。可以在daemon.json文件或者在docker run命令中使用--log - driver参数来配置日志驱动。例如,将容器的日志驱动配置为syslog:
docker run --log - driver=syslog myimage
一、Dockerfile 简介
Dockerfile 是一个文本文件,它包含了一系列用于构建 Docker 镜像的指令。通过这些指令,可以自动化地创建自定义的 Docker 镜像,将应用程序及其依赖项打包到一个独立的、可移植的镜像中。
二、基本指令
(一)基础镜像指令:FROM
指令格式
FROM <image>:<tag>
其中,<image>是基础镜像的名称,可以是官方镜像(如ubuntu、nginx、python等)或者自定义镜像;<tag>是镜像的标签,通常是版本号,例如latest表示最新版本。
示例
如果要基于最新版本的 Ubuntu 构建一个镜像,可以使用:
FROM ubuntu:latest
(二)运行命令指令:RUN
指令格式(shell 形式)
RUN <command>
这种形式下,<command>是在基础镜像的 shell 环境中执行的命令。例如,在 Ubuntu 镜像中安装软件包。
示例(shell 形式)
在基于 Ubuntu 的镜像中安装nginx,可以使用:
RUN apt-get update && apt-get install -y nginx
指令格式(exec 形式)
RUN ["executable", "param1", "param2"]
这种形式适用于执行没有 shell 环境的命令,例如运行一个特定的可执行文件。
示例(exec 形式)
运行一个自定义的 Python 脚本app.py,可以使用:
RUN ["python", "app.py"]
(三)工作目录指令:WORKDIR
指令格式
WORKDIR <path>
<path>是在容器内设置的工作目录,之后的COPY、ADD、RUN等指令将在这个工作目录下执行,除非指定了其他目录。
示例
设置工作目录为/app,可以使用:
WORKDIR /app
(三)复制文件指令:COPY 和 ADD
COPY 指令格式
COPY <src>... <dest>
<src>是本地主机(构建环境)的文件或目录路径,可以是多个文件或目录;<dest>是容器内的目标路径。
示例
将本地的app.py文件复制到容器内的/app目录下,可以使用:
WORKDIR /app
COPY app.py.
ADD 指令格式和特点
ADD <src>... <dest>
ADD指令与COPY类似,但ADD有一些额外的功能。例如,它可以自动解压本地的压缩文件(如.tar.gz)并将其内容添加到容器内的指定目录。不过,在大多数情况下,建议使用COPY指令,除非确实需要解压功能。
示例(解压功能)
将本地的一个压缩文件data.tar.gz添加到容器内并解压到/data目录,可以使用:
ADD data.tar.gz /data
(四)暴露端口指令:EXPOSE
指令格式
EXPOSE <port>[/<protocol>]
<port>是容器内要暴露的端口号,<protocol>是端口对应的协议,通常是tcp或udp,默认是tcp。
示例
暴露容器内的80端口(用于 HTTP 服务),可以使用:
EXPOSE 80
需要注意的是,EXPOSE指令只是一种声明,它本身不会自动将端口映射到主机上。在运行容器时,还需要使用-p或-P参数进行端口映射。
(五)容器启动命令指令:CMD 和 ENTRYPOINT
CMD 指令格式和作用
CMD ["executable", "param1", "param2"](exec 形式)或CMD <command> <param1> <param2>(shell 形式)
CMD 指令用于指定容器启动时默认执行的命令。如果在运行docker run命令时没有指定其他命令,就会执行 CMD 指令中的命令。一个 Dockerfile 中只能有一个 CMD 指令,多个 CMD 指令时只有最后一个生效。
示例(exec 形式)
启动一个 Python 应用,容器启动时默认执行python app.py,可以使用:
CMD ["python", "app.py"]
ENTRYPOINT 指令格式和作用
ENTRYPOINT ["executable", "param1", "param2"](exec 形式)或ENTRYPOINT <command> <param1> <param2>(shell 形式)
ENTRYPOINT 指令也用于指定容器启动时执行的命令,但它的主要目的是设置容器的固定入口点。与 CMD 不同的是,当用户在运行docker run命令时指定了其他命令,这些命令会作为参数附加到 ENTRYPOINT 指定的命令之后,而不是替换它。
示例(exec 形式)
设置一个容器的固定入口为python,可以使用:
ENTRYPOINT ["python"]
这样,当运行docker run命令并指定一个 Python 脚本作为参数时,就会执行这个脚本,例如:docker run myimage myscript.py会执行python myscript.py。
三、构建镜像过程
构建命令
使用docker build命令来构建镜像,格式如下:
docker build -t <image_name>:<tag> <context_path>
其中,-t参数用于指定镜像的名称和标签,<image_name>是镜像名称,<tag>是版本标签;<context_path>是构建上下文路径,通常是包含 Dockerfile 的目录。
2. 构建上下文(Context)
构建上下文是指在构建镜像时,Docker 会将<context_path>目录下的所有文件(除了一些被排除的文件,如.dockerignore文件中指定的文件)发送到 Docker 守护进程(dockerd)。这意味着在构建镜像时,要注意构建上下文的大小,尽量避免将不必要的文件包含在内,以提高构建效率。
3. 构建缓存
Docker 在构建镜像时会使用缓存来加速构建过程。它会检查每条指令及其之前的所有指令是否与之前构建时相同,如果相同,则使用缓存中的结果。例如,如果RUN指令中安装的软件包没有变化,那么 Docker 会使用之前缓存的结果,而不是重新执行安装命令。
四、多阶段构建
概念和优势
多阶段构建是一种优化镜像大小的技术。在构建复杂应用的镜像时,通常需要安装构建工具和依赖项来构建应用,然后在运行时只需要应用本身和运行时依赖项。多阶段构建允许在一个 Dockerfile 中使用多个FROM指令,将构建阶段和运行阶段分开,在构建阶段完成后,只将运行阶段所需的文件复制到最终的镜像中,从而减小镜像体积。
示例
以下是一个简单的 Go 应用的多阶段构建示例:
# 构建阶段
FROM golang:latest as builder
WORKDIR /go/src/app
COPY. /go/src/app
RUN go build -o myapp.
# 运行阶段
FROM alpine:latest
WORKDIR /app
COPY --from=builder /go/src/app/myapp.
CMD ["./myapp"]
在这个示例中,首先使用golang:latest镜像作为构建阶段的基础镜像,构建 Go 应用并生成可执行文件myapp。然后,使用alpine:latest镜像作为运行阶段的基础镜像,将构建阶段生成的myapp文件复制到运行阶段的镜像中,并设置容器启动命令为运行myapp。通过这种方式,可以得到一个体积较小的镜像,因为运行阶段的镜像只包含了应用运行所需的最小依赖项(来自alpine镜像)和应用本身。
五、.dockerignore 文件
作用和格式
.dockerignore文件用于指定在构建镜像时要排除的文件和目录。它的格式与.gitignore文件类似,每行一个模式,用于匹配要排除的文件或目录。
示例
如果不想将本地的.git目录、node_modules目录和test文件包含在构建上下文中,可以在.dockerignore文件中添加以下内容:
.git
node_modules
test
这样可以减小构建上下文的大小,提高构建效率,并且避免将不必要的文件或敏感信息包含在镜像中。