Docker 和 Docker Compose 完整指南:命令和最佳实践
Docker 和 Docker Compose 完整指南:命令和最佳实践
Docker 基本概念
Docker 是一个开源系统,通过容器化促进应用程序的开发、部署和执行。它通过将应用程序及其依赖项打包成自包含、可移植的单元来解决兼容性问题,确保在任何环境中都能一致运行。
核心组件
-
镜像(Images):这些是轻量级、自包含、可执行的软件包,包含运行应用程序所需的一切(代码、运行时、库、配置)。它们是创建容器的虚拟化模板。
-
容器(Containers):这些是 Docker 镜像的运行时实例。它们将软件与其环境隔离,允许在主机上同时运行多个容器。
-
Docker Hub:这是 Docker 提供的用于查找和共享容器镜像的服务。
Docker CLI 命令(基础)
| 任务 | CLI 命令 | 描述 |
|---|---|---|
| 镜像 | ||
| 构建镜像 | docker build -t <image_name> . | 从当前目录的 Dockerfile 构建镜像。 |
| 不使用缓存构建 | docker build -t <image_name> . --no-cache | 强制重新构建而不使用缓存。 |
| 列出镜像 | docker images | 显示所有本地镜像。 |
| 删除镜像 | docker rmi <image_name> | 删除本地镜像。 |
| 删除未使用的镜像 | docker image prune | 删除所有未使用的镜像。 |
| 发布到 Docker Hub | docker push <user>/<image_name> | 将镜像上传到 Docker Hub。 |
| 容器 | ||
| 运行容器(带名称) | docker run --name <container_name> <image_name> | 从镜像创建并运行容器。 |
| 后台运行 | docker run -d <image_name> | 在分离模式(后台)运行容器。 |
| 运行并发布端口 | docker run -p <host_port>:<container_port> <image_name> | 将容器端口映射到主机。 |
| 列出容器(运行中) | docker ps | 显示当前运行的容器。 |
| 列出所有容器(运行和停止) | docker ps --all | 显示所有容器,无论其状态如何。 |
| 启动/停止/重启 | docker start|stop|restart <container_name> | 启动或停止现有容器。docker stop 发送 SIGTERM 信号以优雅关闭。 |
| 删除容器 | docker rm <container_name> | 删除已停止的容器。 |
| 进入容器 | docker exec -it <container_name> sh | 在运行的容器内打开交互式 shell。 |
| 查看日志 | docker logs -f <container_name> | 显示并跟踪容器日志。 |
| 检查容器 | docker inspect <container_name> | 显示容器详细信息,通常为 JSON 格式。 |
| 监控资源 | docker stats | 显示运行时资源使用统计信息。 |
高级 Docker:镜像和安全最佳实践
多阶段构建
多阶段构建优化 Dockerfile 同时保持其可读性。它们允许创建一个小型、安全的生产镜像,只包含必要的二进制文件或工件,而不包含开发工具。
- 用法:使用多个
FROM指令,每个指令开始一个新阶段。 - 选择性复制:使用
COPY --from=<stage>从前面的阶段复制工件。 - 阶段命名:最好使用
FROM <image> AS <NAME>命名阶段,以便更容易引用它们,并避免在重新排序指令时破坏复制:COPY --from=build /bin/hello /bin/hello。 - 调试:可以使用
docker build --target <stage> -t hello .仅构建到特定阶段。 - BuildKit:这是推荐的构建器,因为它只处理目标所依赖的阶段,而传统构建器处理目标之前的所有阶段。
镜像和容器安全
| 实践 | 详细信息 |
|---|---|
| 基础镜像 | 使用来自可靠来源的官方或已验证镜像。从最小基础镜像开始,只包含基本依赖项以最小化漏洞。 |
| 扫描 | 定期扫描镜像和容器的已知漏洞(例如使用 Trivy 或 Docker Scout 等工具)。 |
| 权限 | 遵循最小权限原则。以非 root 用户身份运行容器。 |
| 文件系统 | 尽可能使用只读文件系统。 |
| 内容签名 | 启用Docker 内容信任(DCT)以确保只使用已签名的镜像。 |
Docker Compose(多容器应用管理)
Docker Compose 是一个简化多容器应用管理的工具。它允许在单个 YAML 文件(通常是 docker-compose.yml)中定义和编排多个容器(服务、网络、卷)。
- 与 Docker 的主要区别:Docker 管理单个容器,而 Docker Compose 协调一起工作的多个容器。
- 理想用途:对于需要快速和灵活配置多个服务的开发和测试环境特别有用(例如,Web 应用、数据库和前端)。
- 版本 V2:建议使用最新版本。V1(带连字符:
docker-compose)已停止更新;V2 使用docker compose(不带连字符)。
Compose 结构和基本命令
docker-compose.yml 文件定义结构:
# 注意:在最新的 Docker Compose 版本中,不再需要版本
# version: '3.8' # 在现代版本中可选
services:
service1: # 容器/服务定义
# 服务配置
networks:
network1: # 自定义网络配置
# 网络配置
volumes:
volume1: # 命名卷定义
# 卷配置| 任务 | CLI 命令(V2) | 描述 |
|---|---|---|
| 构建和部署 | docker compose up | 构建并运行 yml 中定义的容器。 |
| 后台部署 | docker compose up -d | 部署并将应用程序留在后台运行。 |
| 停止应用 | docker compose stop | 停止容器。 |
| 停止并删除 | docker compose down | 停止并删除服务和网络。默认不删除命名卷。 |
| 删除并删除卷 | docker compose down --volumes 或 -v | 强制删除服务、网络和命名卷。 |
| 扩展服务 | docker compose up --scale service=n | 增加特定服务的容器数量(n)。 |
| 服务状态 | docker compose ps | 显示容器的当前状态。 |
| 日志 | docker compose logs | 显示定义容器的日志。 |
持久数据管理(卷)
卷对于在容器和主机之间持久化数据至关重要,确保在容器停止或重启时数据不会丢失。
- 命名卷:这些具有用户定义的名称,便于识别和管理。它们在
yml的volumes部分定义,然后在服务中挂载。 - 主机挂载(绑定挂载):允许将主机目录与容器共享,以促进数据访问和编辑。使用的语法是:
/path/on/host:/path/in/container。
| 任务 | CLI 命令(Docker,适用于 Compose 卷) |
|---|---|
| 列出卷 | docker volume ls |
| 检查卷 | docker volume inspect <volume_name> |
| 删除卷 | docker volume rm <volume_name> |
| 清理未使用的卷 | docker volume prune |
Compose 的高级生产最佳实践
密钥和环境变量管理
将关键配置(如数据库凭据和 API 密钥)与应用代码分离,允许更灵活和安全的部署。
- 风险:永远不要硬编码密钥(密码、令牌)在
Dockerfiles中或意外在镜像层中暴露它们。 - 环境文件(
env_file):建议将环境变量存储在.env文件中,并在docker-compose.yml中使用env_file: .env指令引用它。 - 安全:此
.env文件必须从代码仓库中排除(例如使用.gitignore),允许在运行时加载密钥而不在版本控制中暴露。
网络和访问安全
- 内部连接性:默认情况下,在 Compose 中定义的容器在内部相互连接。
- 数据库保护:在
yml中移除数据库端口暴露是一个很好的安全实践(不将端口绑定到主机)。虽然数据库进程声明了端口,但它不会绑定到主机,从而保护数据库免受公开暴露。要访问它,您可以通过 SSH 隧道连接。
资源限制和重启
对于共享环境,限制应用程序可以消耗的资源至关重要,以避免影响其他应用。
- 资源限制(
deploy: resources):允许在服务中指定内存、CPU 或 GPU 的使用限制。- 限制(
limits):应用程序可以拥有的总使用量(例如,cpus: 1,memory: 1GB)。 - 预留(
reservations):容器独占操作预留的 RAM 和 CPU。
- 限制(
- 重启策略(
restart_policy):使用restart: always确保服务器重启时应用程序自动启动至关重要。- 更详细的配置允许定义条件(例如,
on-failure)、延迟(delay)、最大尝试次数(max_attempts)和重启时间窗口(window)。
- 更详细的配置允许定义条件(例如,
健康检查
这些允许定义对容器发起的持续测试,以验证它实际上正在运行,如果失败则重启它。
- 配置:您可以定义
interval(测试发起频率)、retries(在认为它宕机之前失败的次数)、timeout(请求的最大等待时间)和start_period(启动时应用程序启动的时间余量)。
主机安全和一般最佳实践
为了提高运行 Docker Engine 的 Linux 服务器的安全性:
- 限制 Root 访问:限制Root 登录访问(通常在 Ubuntu Server 上默认禁用)。
- RSA 密钥:建议使用RSA(SSH 密钥)而不是密码登录。
- 您可以使用
ssh-keygen创建 SSH 密钥。 - 您可以使用
ssh-copy-id <user>@<server>将公钥复制到服务器。
- 您可以使用
- 暴力攻击防护:安装Fail2Ban(
apt install fail2ban)。此应用程序使用防火墙规则(如 IP Tables)阻止对 SSH 端口进行太多失败尝试的 IP。 - 维护:经常更新 Docker Engine 及其依赖项以减轻漏洞。
- 监控:实施监控系统以记录应用日志并自动检测服务器上的崩溃或资源短缺,此外还使用
docker stats监控资源。
结论
Docker 和 Docker Compose 是现代软件开发中的基本工具。掌握它们的命令和最佳实践不仅提高了开发效率,还确保了生产环境中更安全和可维护的部署。正确实施这些实践允许创建可扩展、可移植和有弹性的应用程序。
要继续您的容器化学习之旅,我建议探索 Kubernetes 编排策略或深入研究镜像优化技术,以进一步减少应用程序的大小和启动时间。