明天你会感谢今天奋力拼搏的你。
ヾ(o◕∀◕)ノヾ
容器技术是一种轻量级的虚拟化技术,它能够在操作系统层面实现资源的隔离和分配,让应用程序及其依赖可以在独立的环境中运行,且不会受到其他应用的干扰。这种技术的核心依赖于 Linux 内核的两大关键特性:NameSpace 和 CGroups。
NameSpace 是 Linux 内核提供的一种隔离机制,它能将进程运行时所需要的各种资源(如进程 ID、网络、文件系统等)进行隔离,使得每个容器内的进程只能看到自己 NameSpace 中的资源,仿佛处于一个独立的系统环境中。
常见的 NameSpace 类型及作用如下:
CGroups(Control Groups)是 Linux 内核提供的一种资源限制机制,它可以对进程组的资源使用进行限制、统计和控制。通过 CGroups,能够为每个容器分配特定的 CPU、内存、磁盘 I/O、网络带宽等资源,防止某个容器过度占用资源而影响其他容器或宿主机器的正常运行。
其主要作用包括:
正是基于 NameSpace 的隔离能力和 CGroups 的资源控制能力,容器技术才能实现轻量级、高效的虚拟化,相比传统的虚拟机技术,具有启动速度快、资源占用少、移植性好等优势。
Docker 是基于容器技术的开源应用容器引擎,它让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。Docker 简化了应用的部署、运行和管理流程,极大地提高了开发、测试和部署的效率。
Docker 的核心概念围绕其运行和管理机制展开,这些概念相互关联,共同支撑起 Docker 的完整功能体系,以下是主要核心概念:
镜像是 Docker 中最基础的核心概念之一,它是一个只读的模板,包含了运行应用程序所需的所有内容,像代码、运行时环境、库、环境变量以及配置文件等。可以将其理解为容器的 “源代码”,是容器运行的基础。
镜像采用分层存储结构,每一层都对应着 Dockerfile 中的一条指令(如 RUN、COPY 等),并且每一层都是独立且只读的。这种分层结构带来了诸多优势,比如不同镜像可以共享相同的层,大大减少了存储空间的占用;同时,当需要修改镜像时,只需在原有层的基础上添加新的层,无需重新构建整个镜像,提高了构建效率。
例如从 DockerHub 下载的 ubuntu 镜像,就包含了 ubuntu 操作系统运行所需的基础文件和配置,基于该镜像可以创建多个不同的容器。
容器是镜像的运行实例,是一个动态的对象。它在镜像的基础上添加了一个可写层,当容器运行时,所有对容器内文件系统的修改(如创建文件、修改配置等)都会被记录在这个可写层中,而原始镜像不会受到任何影响。
容器具有独立、隔离的特性,这得益于 Linux 内核的 NameSpace 和 CGroups 技术。每个容器都有自己独立的进程空间、网络环境、文件系统视图等,就像一个独立的 “小虚拟机”,但相比传统虚拟机更加轻量,启动速度更快,资源占用更少。
通过docker run命令可以基于镜像创建并启动容器,容器可以被启动、停止、重启、删除等。例如基于 ubuntu 镜像创建的容器,在其中安装软件后,停止容器再重新启动,之前安装的软件仍然存在(存储在可写层)。
Docker 引擎是 Docker 的核心运行环境,它由Docker daemon(守护进程)、Docker client(客户端) 以及相关工具和库组成。
仓库是用于存储和分发 Docker 镜像的场所,相当于镜像的 “仓库”。它分为公有仓库和私有仓库:
通过docker push命令可以将本地构建的镜像上传到仓库,使用docker pull命令可以从仓库下载镜像到本地。
数据卷是用于在容器和宿主机器之间或容器之间共享和持久化数据的一种机制。它是独立于容器文件系统的特殊目录,其生命周期不受容器的影响,即使容器被删除,数据卷中的数据仍然保留。
数据卷可以绕过容器的可写层,直接与宿主机器的文件系统进行交互,不仅提高了数据读写性能,还解决了容器内数据持久化的问题。例如在运行数据库容器时,将数据库的数据目录挂载到数据卷,这样即使容器被删除,数据库数据也不会丢失。
通过docker volume create命令可以创建数据卷,在启动容器时通过-v选项将数据卷挂载到容器内的指定目录。
Docker 生态由多个组件构成,它们相互协作,共同完成 Docker 的各项功能:
docker run -it --name mycontainer ubuntu /bin/bash,此命令以交互模式启动一个名为 mycontainer 的容器,使用 ubuntu 镜像,并在容器内执行 /bin/bash 命令。其中,-i表示保持标准输入打开,-t表示分配一个伪终端。docker ps -a,显示所有容器的信息,包括容器 ID、镜像名称、创建时间、状态等。docker inspect mycontainer,查看名为 mycontainer 的容器的详细信息。docker exec -it mycontainer /bin/bash,在 mycontainer 容器中以交互模式执行 /bin/bash 命令,进入容器内部。docker attach mycontainer,连接到 mycontainer 容器,此时在终端输入的命令会在容器内执行。需要注意的是,如果从该终端退出,可能会导致容器停止。docker stop mycontainer,停止 mycontainer 容器的运行。docker start mycontainer,启动已停止的 mycontainer 容器。docker top mycontainer,显示 mycontainer 容器内运行的进程,包括进程 ID、用户、命令等信息。docker rm mycontainer,删除已停止的 mycontainer 容器;docker rm -f mycontainer,强制删除正在运行的 mycontainer 容器。Dockerfile 是一个由一系列指令组成的文本文件,这些指令按顺序执行,用于构建 Docker 镜像。它采用了一种声明式的语法,每一条指令都对应着镜像构建过程中的一个操作,如指定基础镜像、安装软件、设置环境变量等。通过 Dockerfile,开发者可以清晰地记录镜像的构建步骤,使得镜像构建过程可重复、可追溯,方便团队协作和版本控制。
一个完整的 Dockerfile 通常由以下几个部分构成:
常用的 Dockerfile 指令及其作用如下:
FROM 镜像名称[:标签],例如FROM ubuntu:20.04。RUN 命令(shell 形式)和RUN ["可执行文件", "参数1", "参数2"](exec 形式)。例如RUN apt-get update && apt-get install -y nginx。COPY [--chown=用户:组] 源路径 目标路径,例如COPY app.py /app/。ADD test.tar.gz /tmp/。WORKDIR /app。ENV JAVA_HOME /usr/local/jdk。EXPOSE 80。CMD ["可执行文件", "参数1", "参数2"](exec 形式,推荐)、CMD 命令 参数1 参数2(shell 形式)、CMD ["参数1", "参数2"](作为 ENTRYPOINT 的参数)。例如CMD ["nginx", "-g", "daemon off;"]。ENTRYPOINT ["可执行文件", "参数1", "参数2"](exec 形式)和ENTRYPOINT 命令 参数1 参数2(shell 形式)。以下是一个构建简单 Python 应用镜像的 Dockerfile 示例:
# 指定基础镜像
FROM python:3.9-slim
# 设置工作目录
WORKDIR /app
# 复制当前目录下的requirements.txt到镜像的/app目录
COPY requirements.txt .
# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt
# 复制当前目录下的所有文件到镜像的/app目录
COPY . .
# 声明暴露的端口
EXPOSE 5000
# 设置启动命令
CMD \["python", "app.py"]
对应的构建命令:在 Dockerfile 所在目录执行docker build -t mypythonapp:v1 ,即可生成 mypythonapp:v1 镜像。该镜像基于 python:3.9-slim 基础镜像,安装了 requirements.txt 中指定的依赖,复制了应用代码,并设置启动时运行 app.py,暴露 5000 端口。
优化 Docker 镜像可以减小镜像体积、提高构建速度、增强安全性等。常用的优化方法如下:
选择合适的基础镜像:尽量使用体积小的基础镜像,如 Alpine 版本的镜像,相比完整版镜像体积更小。例如使用python:3.9-alpine替代python:3.9。
减少镜像层数:Dockerfile 中每一条 RUN、COPY、ADD 等指令都会创建一个新的镜像层,层数过多会增加镜像体积。可以将多个 RUN 命令合并为一个,使用&&连接命令,并用\进行换行
清理无用文件:在每个 RUN 指令中,及时清理安装过程中产生的临时文件、缓存文件等,如apt-get clean、rm -rf等命令。
使用多阶段构建:多阶段构建可以将构建过程分为多个阶段,只将最终需要的文件复制到最终镜像中,减少镜像体积。例如,在构建 Go 应用时,第一阶段使用包含编译工具的镜像进行编译,第二阶段使用基础镜像,只复制编译好的可执行文件。
合理使用 COPY 和 ADD:优先使用 COPY 指令,因为它功能更单一、更安全;ADD 指令的自动解压和 URL 下载功能可能会引入不必要的文件,增加镜像体积。
避免使用RUN apt-get upgrade:升级系统包可能会导致镜像不稳定,且会增加镜像体积,如需特定版本的包,在安装时指定即可。
全部评论