15.1 Linux Docker容器技术
15.1 Linux Docker容器技术
Docker 是一个开源的容器化平台,允许开发者打包应用以及应用的依赖环境到一个可移植的容器中,然后发布到任何支持 Docker 的平台上。容器技术在开发、测试和生产环境中提供了一致性,简化了应用的部署和管理。
15.1.1 理解容器与虚拟机的区别
容器和虚拟机都是现代云计算环境中常用的技术,它们提供了不同级别的隔离和抽象,适用于不同的应用场景。以下是容器和虚拟机之间关键区别的详细说明:
-
容器(Containers):
- 轻量级:容器共享宿主机的操作系统内核,不需要模拟整个操作系统,因此启动和运行速度更快,资源消耗也更少。
- 直接运行:容器直接在宿主机的操作系统上运行,它们使用宿主机的内核和部分系统库。
- 隔离性:虽然容器提供了一定程度的隔离,但它们之间的隔离性不如虚拟机。容器共享宿主机的内核和系统调用接口。
- 可移植性:容器可以在不同的宿主机之间轻松迁移,因为它们不依赖于特定的底层硬件或操作系统。
- 开发和部署:容器非常适合微服务架构和持续集成/持续部署(CI/CD)流程,因为它们可以快速构建、测试和部署。
-
虚拟机(Virtual Machines):
- 资源占用:虚拟机需要模拟整个硬件系统,包括CPU、内存、硬盘和网络接口等,因此占用更多的系统资源。
- 完整的操作系统:每个虚拟机都运行一个完整的操作系统副本,这使得它们在隔离性和安全性方面更强。
- 灵活性:虚拟机可以运行任何操作系统,包括不同的操作系统版本和配置,这为运行特定应用提供了灵活性。
- 性能开销:由于需要模拟硬件和运行完整的操作系统,虚拟机的性能通常低于容器。
- 管理工具:虚拟机通常需要更复杂的管理工具和更多的配置工作,例如虚拟机监控程序(VMM)和虚拟化管理平台。
-
性能:
- 容器:由于容器共享宿主机的内核和系统资源,它们通常具有更好的性能和更快的启动时间。
- 虚拟机:虚拟机的性能受限于它们模拟的硬件资源和操作系统的开销。
-
安全性:
- 容器:容器之间的隔离主要依赖于容器运行时的安全性。虽然容器可以提供一定程度的隔离,但它们之间的界限不如虚拟机严格。
- 虚拟机:虚拟机提供了更强的隔离性,每个虚拟机都有独立的操作系统和硬件抽象层,这为安全运行提供了更好的保障。
-
应用场景:
- 容器:适用于微服务架构、开发和测试环境、CI/CD流程、以及需要快速迭代和部署的场景。
- 虚拟机:适用于需要运行不同操作系统、需要严格隔离、或者需要模拟特定硬件环境的场景。
综上所述,容器和虚拟机各有优势和适用场景。在选择使用容器还是虚拟机时,需要根据具体的业务需求、性能要求、安全性考虑和资源限制来决定。随着技术的发展,容器和虚拟机也在不断融合和互补,以满足更广泛的云计算需求。
15.1.2 安装 Docker
Docker 是一个流行的开源容器化平台,它允许开发者将应用及其依赖打包在容器中,实现环境一致性和快速部署。以下是在不同 Linux 发行版上安装 Docker 的步骤:
Debian/Ubuntu 系统安装 Docker
-
更新软件包列表:
首先,更新你的软件包列表以确保你安装的是最新版本的软件包。sudo apt update
-
安装所需的包:
安装一些必要的包,这些包用于添加 Docker 官方 GPG 密钥,以及设置存储库。sudo apt install apt-transport-https ca-certificates curl software-properties-common
-
添加 Docker 的官方 GPG 密钥:
添加 Docker 的官方 GPG 密钥,确保你从 Docker 信任的源安装软件。curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
-
添加 Docker 存储库:
添加 Docker 的官方 APT 存储库,以便你可以安装 Docker 引擎。sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
-
再次更新软件包列表:
更新软件包列表,以确保你安装的是最新版本的 Docker。sudo apt update
-
安装 Docker CE:
安装 Docker 社区版(Docker CE)。sudo apt install docker-ce docker-ce-cli containerd.io
-
验证 Docker 是否安装成功:
验证 Docker 是否正确安装并运行。sudo docker run hello-world
CentOS 系统安装 Docker
-
安装所需的包:
安装一些必要的包,这些包用于添加 Docker 官方 GPG 密钥,以及设置存储库。sudo yum install yum-utils
-
添加 Docker 的官方 GPG 密钥:
添加 Docker 的官方 GPG 密钥,确保你从 Docker 信任的源安装软件。yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
-
安装 Docker CE:
安装 Docker 社区版(Docker CE)。sudo yum install docker-ce docker-ce-cli containerd.io
-
启动 Docker 服务:
启动 Docker 服务并设置开机自启。sudo systemctl start docker sudo systemctl enable docker
-
验证 Docker 是否安装成功:
验证 Docker 是否正确安装并运行。sudo docker run hello-world
通用步骤
-
添加用户到 Docker 组(可选):
如果你希望在非 root 用户下运行 Docker 命令,可以将用户添加到 Docker 组。sudo usermod -aG docker your-username
添加用户到 Docker 组后,你需要注销并重新登录,或者重启系统以使组成员变更生效。
-
安装 Docker Compose(可选):
Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。你可以从 Docker Compose 的 GitHub 仓库 下载并安装它。
通过这些步骤,你可以在 Linux 系统上成功安装 Docker,并开始使用容器技术。安装完成后,你可以开始创建、运行和管理 Docker 容器和镜像。
15.1.3 启动 Docker 服务
在 Docker 安装完成后,你需要确保 Docker 服务已经启动并设置为开机自启动,这样 Docker 服务就会在系统启动时自动运行。以下是启动 Docker 服务并设置开机自启的步骤:
-
启动 Docker 服务:
使用systemctl
命令启动 Docker 服务。这个命令会启动 Docker 守护进程,使其在后台运行。sudo systemctl start docker
这个命令在首次安装 Docker 后是可选的,因为 Docker 通常会自动启动。
-
设置开机自启:
使用systemctl
命令设置 Docker 服务开机自启动。这确保了每次系统启动时,Docker 服务也会自动启动。sudo systemctl enable docker
这个命令会创建一个符号链接,将 Docker 服务与系统的启动目标相连接。
-
检查 Docker 服务状态:
使用systemctl
命令检查 Docker 服务的状态,确保它正在运行。sudo systemctl status docker
如果 Docker 服务正在运行,你将看到
active (running)
状态。 -
检查 Docker 版本:
使用docker
命令检查 Docker 的版本,确保安装的是最新版本。sudo docker --version
或者使用以下命令:
sudo docker version
-
运行测试容器:
为了验证 Docker 是否正确安装和运行,你可以运行一个测试容器,如hello-world
镜像。sudo docker run hello-world
如果 Docker 运行正常,这个命令将下载一个测试镜像,并在容器中运行它,输出一条欢迎消息。
-
添加用户到 Docker 组(可选):
如果你希望在非 root 用户下运行 Docker 命令,可以将用户添加到 Docker 组。sudo usermod -aG docker your-username
添加用户到 Docker 组后,你需要注销并重新登录,或者重启系统以使组成员变更生效。
-
配置 Docker 镜像加速器(可选):
为了加速 Docker 镜像的下载,你可以配置 Docker 镜像加速器。编辑 Docker 配置文件:sudo nano /etc/docker/daemon.json
添加以下内容(替换
<your-mirror>
为实际的加速器地址):{ "registry-mirrors": ["<your-mirror>"] }
保存文件并重启 Docker 服务:
sudo systemctl restart docker
通过这些步骤,你可以确保 Docker 服务在你的 Linux 系统上正确安装和运行。接下来,你可以开始创建和运行 Docker 容器,以及管理 Docker 镜像。
15.1.4 验证 Docker 安装
验证 Docker 是否正确安装是确保 Docker 可以正常工作的重要步骤。hello-world
镜像是 Docker 提供的一个简单的测试镜像,它用于验证 Docker 是否能够成功运行一个容器。以下是详细的验证步骤:
-
运行 hello-world 容器:
在终端或命令行界面中,输入以下命令来运行hello-world
容器:docker run hello-world
这个命令会从 Docker Hub(Docker 的官方镜像仓库)拉取
hello-world
镜像(如果本地没有的话),创建并启动一个容器。 -
查看输出信息:
如果 Docker 正确安装,并且系统能够连接到 Docker Hub,你将看到一条欢迎消息,表示 Docker 容器正在运行。典型的输出信息如下:Hello from Docker! This message shows that your installation appears to be working correctly. Get started with your own container! Visit https://docs.docker.com/engine/userguide/ to learn how to create your first container with Docker.
这条消息表明 Docker 运行正常,并且你的系统已经准备好运行自己的容器。
-
检查容器列表:
为了确认hello-world
容器已经运行过,你可以列出所有运行过的容器:docker ps -a
这将显示一个包含所有容器的列表,包括
hello-world
容器。你应该会看到hello-world
容器的状态为Exited
,表示它已经成功运行并退出。 -
清理不再需要的容器:
如果需要,你可以清理不再需要的容器以释放磁盘空间。例如,删除hello-world
容器:docker rm hello-world
这将从系统中删除指定的容器。
-
验证 Docker 版本:
另外,你还可以通过检查 Docker 的版本来确认 Docker 是否正确安装:docker --version
或者使用更详细的版本信息命令:
docker version
这些命令将显示 Docker 客户端和服务器的版本信息。
-
检查 Docker 信息:
使用以下命令可以获取有关 Docker 环境的详细信息,包括 Docker 版本、运行时、图像和容器的数量等:docker info
通过上述步骤,你可以验证 Docker 是否已经正确安装在你的系统上,并且可以开始运行容器。如果 hello-world
容器成功运行并显示了欢迎消息,那么你的 Docker 安装就成功了。如果遇到任何问题,可能需要检查 Docker 的安装步骤或查看 Docker 的日志文件以获取错误信息。
15.1.5 管理 Docker 容器
Docker 容器管理涉及一系列操作,包括拉取镜像、运行容器、列出容器、停止容器以及删除容器。以下是这些操作的详细说明和使用示例:
-
拉取镜像:
- 从 Docker Hub 或其他 Docker 镜像仓库拉取镜像到本地。
docker pull ubuntu
- 这将下载最新的
ubuntu
镜像到本地 Docker 镜像库。
-
运行容器:
- 创建并启动一个新的容器实例。
docker run -it ubuntu /bin/bash
- 这个命令会从
ubuntu
镜像创建并启动一个新容器,并打开一个交互式终端会话。-it
参数是--interactive
和--tty
的缩写,它们让 Docker 提供一个交互式 shell。
-
列出容器:
- 列出当前正在运行的容器。
docker ps
- 列出所有容器(包括未运行的)。
docker ps -a
- 这些命令帮助你查看容器的 ID、创建时间、状态、端口等信息。
-
停止容器:
- 停止一个正在运行的容器。
docker stop container_id
- 替换
container_id
为你想要停止的容器的 ID 或名称。容器停止后,其状态会变为 “Exited”。
-
删除容器:
- 删除一个已停止的容器。
docker rm container_id
- 替换
container_id
为你想要删除的容器的 ID 或名称。删除容器后,它将不再存在于本地环境中。
-
启动容器:
- 启动一个已停止的容器。
docker start container_id
- 这允许你重新启动之前停止的容器,而不是从头开始创建新的容器。
-
重启容器:
- 重启一个容器。
docker restart container_id
- 这个命令会停止并重新启动指定的容器。
-
进入运行中的容器:
- 使用
exec
命令进入一个正在运行的容器的命令行。
docker exec -it container_id /bin/bash
- 这允许你在容器内执行命令或启动新的进程。
- 使用
-
查看容器日志:
- 查看容器的日志输出。
docker logs container_id
- 这可以帮助你了解容器内部发生了什么,特别是对于调试问题很有用。
-
删除镜像:
- 删除一个 Docker 镜像。
docker rmi image_id
- 替换
image_id
为你想要删除的镜像的 ID 或名称。删除镜像后,它将不再存在于本地环境中。
- 替换
- 删除一个 Docker 镜像。
-
清理未使用的资源:
- 清理悬空的镜像、停止的容器、未使用的网络等。
docker system prune
- 这个命令帮助你清理未使用的 Docker 资源,释放磁盘空间。
- 清理悬空的镜像、停止的容器、未使用的网络等。
通过这些基本的 Docker 容器管理命令,你可以有效地控制 Docker 容器的生命周期,从创建、运行到停止和删除。掌握这些命令对于 Docker 用户来说至关重要,无论是在开发、测试还是生产环境中。
15.1.6 Docker 镜像管理
Docker 镜像是容器运行的基础,它包含了容器运行所需的代码、运行时、库、环境变量和配置文件。管理 Docker 镜像包括创建、推送到仓库、拉取以及删除等操作。以下是这些操作的详细说明和使用示例:
-
创建镜像:
- 使用
docker build
命令根据 Dockerfile 创建一个新的镜像。
docker build -t myapp .
- 这个命令会在当前目录(
.
表示当前目录)查找名为Dockerfile
的文件,并根据该文件中的指令构建一个新的镜像,标签为myapp
。
- 使用
-
推送镜像到仓库:
- 使用
docker push
命令将本地镜像推送到 Docker 仓库,如 Docker Hub。
docker push myapp
- 在推送之前,你需要先登录到 Docker Hub 或其他私有仓库:
docker login
- 然后输入你的用户名和密码。
- 使用
-
拉取镜像:
- 使用
docker pull
命令从 Docker 仓库拉取镜像到本地。
docker pull myapp
- 这个命令会从 Docker Hub 或配置的镜像仓库中拉取名为
myapp
的镜像。
- 使用
-
列出本地镜像:
- 使用
docker images
命令列出本地所有的镜像。
docker images
- 你可以使用
-q
参数只显示镜像 ID 列表。
- 使用
-
删除本地镜像:
- 使用
docker rmi
命令删除一个或多个本地镜像。
docker rmi myapp
- 如果镜像正在被使用,你可能需要先停止或删除使用该镜像的容器。
- 使用
-
标记镜像:
- 使用
docker tag
命令为本地镜像添加一个新的标签。
docker tag myapp myusername/myapp:v1
- 这允许你为推送到仓库的镜像设置版本标签或其他标识符。
- 使用
-
构建镜像的最佳实践:
- 保持 Dockerfile 简洁,只包含必要的指令。
- 使用多阶段构建减小镜像大小。
- 清理不必要的文件和缓存以减小镜像大小。
- 确保镜像中的软件包是最新的,并及时更新安全补丁。
-
扫描镜像中的漏洞:
- 使用 Docker 官方提供的工具或第三方工具定期扫描镜像中的安全漏洞。
-
设置镜像自动构建:
- 在 Docker Hub 或其他支持自动构建的仓库中,可以设置在代码更新时自动构建镜像。
通过这些 Docker 镜像管理操作,你可以有效地控制镜像的生命周期,确保镜像的安全性和更新。这些操作对于开发、测试和生产环境中的 Docker 用户来说都是非常重要的。
15.1.7 Dockerfile 编写
Dockerfile
是用于定义 Docker 镜像内容的文本文件,它包含了用于构建镜像的所有命令和指令。一个 Dockerfile
通常包含以下指令:
-
FROM:
- 指定基础镜像,这是构建新镜像的起点。
FROM python:3.8
- 这里使用官方的 Python 3.8 镜像作为父镜像。
-
WORKDIR:
- 设置容器内的当前工作目录。
WORKDIR /app
- 这将
/app
设为工作目录,后续的RUN
、CMD
、ENTRYPOINT
指令都会在这个目录下执行。
-
COPY:
- 将本地文件复制到容器内。
COPY . /app
- 这将构建上下文(通常是
Dockerfile
所在的目录)中的所有文件复制到容器的/app
目录。
-
RUN:
- 执行命令并创建新的镜像层。
RUN pip install --trusted-host pypi.python.org -r requirements.txt
- 这将安装
requirements.txt
文件中列出的所有 Python 依赖。
-
EXPOSE:
- 声明容器运行时监听的端口。
EXPOSE 80
- 这表示容器将公开 80 端口供外部访问。
-
ENV:
- 设置环境变量。
ENV NAME World
- 这将在容器内设置一个名为
NAME
的环境变量,值为World
。
-
CMD:
- 指定容器启动时执行的默认命令。
CMD ["python", "app.py"]
- 这将设置容器启动时执行
python app.py
命令。
-
ENTRYPOINT(可选):
- 设置容器的入口点,可以与
CMD
配合使用。
ENTRYPOINT ["python", "entrypoint.sh"]
- 设置容器的入口点,可以与
-
ADD(不推荐):
- 类似于
COPY
,但ADD
可以自动解压缩 tar 压缩文件。
ADD archive.tar.gz /
- 由于
ADD
在处理本地文件时有潜在的安全风险,通常建议使用COPY
。
- 类似于
-
ARG(可选):
- 定义构建时的变量。
ARG BUILD_DATE ARG VCS_REF
- 这些变量可以在构建过程中使用,并且可以通过
--build-arg
选项传递给docker build
命令。
- 定义构建时的变量。
-
HEALTHCHECK(可选):
- 指定如何检查容器内服务的健康状态。
HEALTHCHECK --interval=30s --timeout=30s --retries=3 CMD curl -f http://localhost/ || exit 1
- 指定如何检查容器内服务的健康状态。
-
USER(可选):
- 指定运行容器时的用户名。
USER nobody
- 指定运行容器时的用户名。
-
VOLUME(可选):
- 创建挂载点,用于数据持久化或共享。
VOLUME /var/www
- 创建挂载点,用于数据持久化或共享。
-
STOPSIGNAL(可选):
- 指定停止容器时发送的信号。
STOPSIGNAL SIGINT
- 指定停止容器时发送的信号。
编写 Dockerfile
时,应该尽量保持简洁明了,并且遵循最佳实践,例如使用多阶段构建来减小镜像大小,避免在镜像中包含不必要的文件。一个良好的 Dockerfile
可以提高构建的效率和镜像的安全性。
15.1.8 Docker Compose
Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过使用 Docker Compose,你可以使用一个 YAML 文件来配置你的应用服务,然后使用一个简单的命令来启动和停止所有服务。
安装 Docker Compose
在 Debian/Ubuntu 系统上安装 Docker Compose:
sudo apt update
sudo apt install docker-compose
在 CentOS 系统上安装 Docker Compose:
sudo yum install docker-compose
你也可以选择从源代码编译或下载预编译的二进制文件来安装 Docker Compose。
编写 docker-compose.yml
docker-compose.yml
文件定义了多容器应用程序的配置。以下是一个基本的 docker-compose.yml
文件示例:
version: '3'
services:
web:
image: "nginx:alpine"
ports:
- "80:80"
depends_on:
- db
db:
image: "postgres:alpine"
environment:
POSTGRES_DB: mydatabase
POSTGRES_USER: user
POSTGRES_PASSWORD: password
在这个示例中,定义了两个服务:web
和 db
。web
服务使用 nginx:alpine
镜像,并映射了容器的 80 端口到宿主机的 80 端口。db
服务使用 postgres:alpine
镜像,并设置了环境变量来配置 PostgreSQL 数据库。
启动服务
使用以下命令启动所有服务:
docker-compose up
这个命令将根据 docker-compose.yml
文件中定义的配置启动所有服务。服务将在前台运行,你可以通过 Ctrl+C 来停止它们。
其他 Docker Compose 命令
-
启动服务(后台运行):
docker-compose up -d
-d
参数告诉 Docker Compose 在后台运行服务。 -
停止服务:
docker-compose down
这个命令将停止并删除由
docker-compose.yml
定义的所有服务。 -
查看服务状态:
docker-compose ps
这个命令将列出所有服务的状态。
-
查看服务日志:
docker-compose logs
这个命令将显示所有服务的日志输出。
-
重新启动服务:
docker-compose restart
这个命令将重启所有服务。
-
构建服务:
docker-compose build
如果你的服务需要构建自定义镜像,可以使用这个命令。
Docker Compose 非常适合开发、测试和生产环境中的多容器 Docker 应用程序。通过使用 Docker Compose,你可以简化多容器应用的部署和管理过程。
15.1.9 安全和最佳实践
在使用 Docker 容器技术时,遵循安全最佳实践是非常重要的。这不仅可以保护你的容器免受攻击,还可以确保容器化应用的稳定性和可靠性。以下是一些关键的安全最佳实践:
-
使用最小化基础镜像:
- 选择最小化的镜像作为容器的基础,如
alpine
,这样可以减少镜像的体积,降低潜在的安全风险。
FROM alpine:latest
- 选择最小化的镜像作为容器的基础,如
-
限制容器权限:
- 不要以 root 用户运行容器,因为 root 权限会提高安全风险。创建一个非 root 用户并在容器内使用该用户运行应用。
RUN groupadd -r myapp && useradd -r -g myapp myapp USER myapp
-
定期更新镜像:
- 定期更新你的 Docker 镜像,以确保它们包含最新的安全补丁和更新。
- 使用
docker pull
命令定期拉取最新版本的官方镜像。
-
隔离生产环境:
- 使用分离的环境进行开发、测试和生产,以减少潜在的风险和错误。
-
使用 Docker 安全扫描工具:
- 利用 Docker 官方的安全扫描工具或第三方工具,如 Anchore、Clair 或 Aqua Security,定期扫描镜像中的漏洞。
-
最小化容器的攻击面:
- 移除不必要的软件包和服务,减少容器内的潜在攻击点。
-
使用安全配置:
- 利用 Docker 的安全配置选项,如 seccomp、apparmor 或 SELinux,来限制容器的行为。
-
管理敏感数据:
- 不要在 Dockerfile 或镜像中硬编码敏感数据,如密码和密钥。使用环境变量或 Docker secrets 管理这些数据。
-
限制容器的网络访问:
- 仅开放必要的端口,并使用网络策略限制不必要的网络访问。
-
使用 Docker 用户命名空间:
- 利用用户命名空间隔离容器内的进程,避免它们获得过高的权限。
-
实施资源限制:
- 使用 Docker 的资源限制功能,如 CPU 和内存限制,防止单个容器占用过多资源。
-
保持 Docker 引擎更新:
- 定期更新 Docker 引擎,以确保你使用的是包含最新安全修复的版本。
-
审计和日志记录:
- 启用容器的审计和日志记录功能,以便监控和分析容器的行为。
-
遵循官方文档和指导:
- 遵循 Docker 官方文档中的最佳实践和安全指导。
通过遵循这些安全最佳实践,你可以大大降低容器化应用的风险,确保它们在各种环境中安全、可靠地运行。安全是一个持续的过程,需要不断地评估和更新以应对新的威胁和挑战。