原创

从零开始理解容器化技术

温馨提示:
本文最后更新于 2025年04月18日,已超过 17 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

 

一、什么是 Docker

1. 概念

Docker 是一个开源的应用容器引擎,帮助开发者在任何地方快速构建、分享、运行和验证应用程序,而无需繁琐的环境配置或管理。它通过以下四个步骤简化了应用开发流程:

  • Build (构建):使用 Dockerfile 定义应用程序及其所有依赖项,并将其打包到一个独立的容器镜像中,确保无论在哪里运行,应用程序都能保持一致的行为。
  • Share (分享):容器可以轻松地在不同的开发团队成员之间共享,甚至可以在不同的环境中(如开发、测试和生产)之间共享,便于协作与部署。
  • Run (运行):容器可以在任何支持 Docker 的环境中运行,无论是本地机器还是云端服务器,这极大地提高了部署的灵活性和效率。
  • Verify (验证):通过容器化,你可以确保应用程序在不同环境中的行为一致,从而更容易进行测试和验证。

2. 架构

Docker 系统主要由三部分组成:

  • Client(客户端):用户通过命令行工具(如 docker-cli)或其他 API 客户端与 Docker 进行交互。
  • Docker Host(Docker 主机):运行 Docker 守护进程(Docker Daemon),负责管理镜像、容器等资源。
  • Registry(镜像仓库):存储和分发镜像的平台,包括公共仓库(如 Docker Hub)和私有仓库。

3. 工作流程

  • Pull: 使用 docker pull 命令从 Registry 下载镜像到 Docker Host。
  • Run: 使用 docker run 命令在 Docker Host 上启动并运行容器。
  • Build: 使用 docker build 命令基于 Dockerfile 创建新的镜像。
  • Push: 使用 docker push 命令将新创建的镜像上传到 Registry。

二、常用命令

1. 镜像操作

  • 搜索镜像
docker search nginx
  • 拉取镜像
拉取latest标签的镜像,没有latest标签则会报错 Error: No such image
docker pull nginx:1.19
# 拉取指定版本镜像
docker pull nginx:1.19
  • 查看本地镜像列表
# 列出所有镜像
docker images
# 仅输出镜像 ID
docker images -q
  • 删除本地镜像
# 删除单个镜像
docker rmi nginx
# 强制删除名称包含 "test" 的镜像
docker rmi $(docker images --filter=reference='*test*' -q)

2. 容器操作

  • 创建并启动容器

核心参数

-d:后台运行(detach 模式)

--name:指定容器名称(避免随机命名)

-p:端口映射(主机端口:容器端口

-v:卷挂载(主机路径:容器路径

--restart:重启策略(no/on-failure/always/unless-stopped

-e:设置环境变量(如 -e MYSQL_ROOT_PASSWORD=123456

--memory:限制内存(如 --memory=4g

--cpus:限制CPU核心(如 --cpus=2

--cpu-shares:调整 CPU 使用的相对权重,默认值是1024(如 --cpu-shares=512

--memory-swap:内存 + 交换分区总限制(设为 -1 表示禁用交换)。

docker run -d --name mysql-server \
  --restart unless-stopped \          # 自动重启策略
  --network mysql-net \
  --memory="2g" \                     # 限制内存
  --cpus="1.5" \                      # 限制 CPU
  -p 3306:3306 \
  -v mysql_data:/var/lib/mysql \      # 数据持久化
  -v /host/mysql/conf.d:/etc/mysql/conf.d \
  -v /host/mysql/logs:/var/log/mysql \
  -e MYSQL_ROOT_PASSWORD="123456" \ 
  -e TZ=Asia/Shanghai \               # 设置时区
  mysql:8.0 \
  --default-authentication-plugin=mysql_native_password  # 兼容旧客户端

卷映射:

Docker 自动创建卷和存储目录,语法为-v volume_name:/container/path,可以使用docker volume inspect volume_name查看详细信息,Docker托管的默认路径为/var/lib/docker/volumes/。文件以容器为主。

目录挂载:

必须手动创建宿主机目录,否则报错,语法为-v /host/path:/container/path。文件以宿主机为主。

  • 启停容器
# 停止 web 和 redis 容器
docker stop web redis 
# 启动容器,容器ID为1ff9ef97ba4d,可以不用输入完整容器ID,能唯一标识即可
docker start 1ff
# 重启容器
docker restart redis
  • 查看容器列表
# 列出所有退出的容器 ID
docker ps -a -q -f status=exited
  • 实时资源监控
# 监控所有运行中容器
docker stats

# 仅监控特定容器(如 web 和 mysql)
docker stats web mysql
  • 日志

核心参数

-f:实时跟踪日志(类似 tail -f

--tail:显示最后 N 行(如 --tail 100

-t:显示时间戳

--since:指定时间范围(如 --since 2024-01-01

# 实时查看 nginx 容器的日志并显示时间戳
sudo docker logs --tail 500 -f -t nginx
  • 进入容器

参数

-it:分配交互式终端。

docker exec -it mysql /bin/bash
docker exec -it mysql mysql -u root -p123456 -e "CREATE DATABASE appdb;"
  • 删除容器

参数

-f:强制删除运行中的容器

-v:同时删除关联的匿名卷

# 强制删除所有容器
docker rm -f $(docker ps -aq)
  • 修改资源限制
docker update --memory=3g --cpus=1.5 mysql
  • 查看容器资源配置
docker inspect mysql_container

3. 镜像管理

保存镜像

使用 docker commit 命令可以基于现有容器的更改创建一个新的镜像。这对于快速保存对容器所做的修改(例如安装软件或更新配置)非常有用。

  • 参数说明
    • -a--author:指定作者。
    • -m--message:提交信息,描述此次提交的内容。
    • -c--change:应用 Dockerfile 指令(如 CMD、ENV 等),以在创建新镜像时进行一些额外的修改。
  • 示例:基于名为 nginx 的容器创建一个名为 my-nginx:v1 的新镜像,并添加提交信息和作者信息。
docker commit -a "Dev Team" -m "Updated homepage" nginx my-nginx:v1

镜像离线备份

将一个或多个镜像打包为 .tar 归档文件,保留完整分层结构,以便于迁移或备份。

# 导出单个镜像
docker save -o nginx-alpine.tar nginx:alpine
# 导出多个镜像并压缩
docker save nginx:alpine redis:6.0 | gzip > apps.tar.gz

恢复镜像

.tar 文件恢复镜像到本地仓库,支持直接加载压缩文件。

docker load -i apps.tar.gz

登录镜像仓库

登录到 Docker 镜像仓库(如 Docker Hub、私有仓库),获取推送/拉取权限。

参数说明

-u:用户名。

-p:密码(不建议在命令行中明文输入,可交互式输入或通过环境变量设置)。

SERVER:仓库地址(默认为 docker.io)。

# 登录 Docker Hub
docker login -u your-username
# 登录私有仓库
docker login registry.example.com -u admin

镜像标记

为镜像创建别名(支持仓库前缀),便于版本管理和推送至指定仓库。

# 将本地镜像标记为仓库格式,未指定 REGISTRY_HOST 时默认使用 Docker Hub (docker.io)。
docker tag my-app:v1 registry.example.com/project/my-app:1.0

镜像推送

将本地镜像上传至远程仓库,实现镜像共享或持久化存储。

# 推送至 Docker Hub
docker push your-username/my-app:1.0
# 推送至私有仓库
docker push registry.example.com/project/my-app:1.0

4. 网络

Docker0网络

Docker 安装时自动创建的桥接网络(bridge 驱动)。默认子网为 172.17.0.0/16,容器分配 172.17.0.x。此网络不支持容器名称自动解析,依赖静态 IP 或链接。

自定义网络

  • Bridge Network(桥接网络):类似于 docker0 的自定义桥接网络,但它允许你指定子网和网关,提供更好的隔离性和控制能力。
# 创建自定义桥接网络
docker network create --driver bridge my_bridge_network
  • Overlay Network(覆盖网络):用于多宿主机部署的 Docker Swarm 或 Kubernetes 集群环境中,支持跨多个 Docker 守护进程的容器间通信。
# 创建 Overlay 网络(需在 Swarm 模式下)
docker network create -d overlay my_overlay_network
  • Host Network(主机网络):容器直接使用宿主机的网络栈,没有网络隔离。这种方式适用于需要最高性能的应用场景,但失去了容器间的网络隔离。
# 使用 Host 网络启动容器
docker run --network host ...

三、Docker Compose

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过 docker-compose.yml 文件,您可以配置应用程序的服务(如Web服务、数据库等)、网络以及卷等资源。只需一个命令即可创建并启动所有配置的服务。

基本概念

  • 服务 (Service):在 Docker Compose 中,一个服务就是容器的一个实例。可以指定服务使用的镜像、端口映射、依赖关系等。
  • 项目 (Project):默认情况下,项目的名称与包含 docker-compose.yml 文件的目录名称相同。可以通过 -p 参数自定义项目名。
  • 网络 (Networks) 和 卷 (Volumes):允许您定义共享网络和持久化存储,便于容器间通信和数据持久化。

示例 docker-compose.yml 配置

version: '3.8'

services:
  app:
    build: .
    ports:
      - "8000:8000"
    restart: unless-stopped
    depends_on:
      redis:
        condition: service_healthy  # 等待 Redis 健康后再启动
      mysql:
        condition: service_healthy  # 等待 MySQL 健康后再启动
    deploy:
      resources:
        limits:
          cpus: '1.0'     # 限制最多使用 1 个 CPU 核心
          memory: 1G      # 限制最大内存为 1GB
    healthcheck:          # 应用健康检查
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
    restart: always
    volumes:
      - redis_data:/data
    deploy:
      resources:
        limits:
          cpus: '0.5'     # Redis 限制 0.5 核
          memory: 512M    # 内存限制 512MB
    healthcheck:          # Redis 健康检查
      test: ["CMD", "redis-cli", "ping"]
      interval: 20s
      timeout: 5s
      retries: 3

  mysql:
    image: mysql:8.0
    ports:
      - "3306:3306"
    restart: on-failure
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: mydb
    volumes:
      - mysql_data:/var/lib/mysql
    deploy:
      resources:
        limits:
          cpus: '0.5'     # MySQL 限制 0.5 核
          memory: 512M    # 内存限制 512MB
    healthcheck:          # MySQL 健康检查
      test: ["CMD", "mysqladmin", "ping", "-uroot", "-p$${MYSQL_ROOT_PASSWORD}"]
      interval: 30s
      timeout: 10s
      retries: 5

volumes:
  redis_data:
  mysql_data:

常用命令

  • 上线: 使用 docker compose up -d 启动所有服务并在后台运行。
  • 下线: 使用 docker compose down 停止并删除所有服务及其相关资源(如网络和卷)。
  • 启动特定服务: 使用 docker compose start x1 x2 x3 启动指定的服务。
  • 停止特定服务: 使用 docker compose stop x1 x3 停止指定的服务。
  • 扩容: 使用 docker compose scale x2=3 将指定服务的实例数量扩展到3个。
  • 更新配置: 使用 docker-compose -f compose.yml up -d 应用新的配置文件更改。
  • 清理: 使用 docker compose -f compose.yaml down --rmi all -v 停止服务并删除所有镜像和卷。

四、Dockerfile

编写 Dockerfile 来构建 Spring Boot 应用的 Docker 镜像:

# 第一阶段:使用官方的 OpenJDK 基础镜像作为构建环境
FROM openjdk:17-jdk-alpine AS build

# 设置工作目录
WORKDIR /app

# 将当前目录下的所有文件复制到容器内的 /app 目录
COPY . .

# 构建 Spring Boot 应用程序(如果需要的话)
# 这一步取决于您的项目是如何构建的,可能需要安装 Maven 或 Gradle 等工具。
# 如果您已经有了 jar 包,这步可以省略
# RUN ./mvnw clean package -DskipTests

# 第二阶段:创建轻量级的运行时镜像
FROM openjdk:17-jre-alpine

# 设置工作目录
WORKDIR /app

# 从构建阶段复制最终的 jar 包到运行时镜像中
COPY --from=build /app/target/springboot-app.jar /app/app.jar

# 暴露应用程序运行所需的端口(根据实际情况调整)
EXPOSE 8080

# 定义启动命令
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

构建 Docker 镜像

在包含 Dockerfile 的目录下运行以下命令来构建 Docker 镜像:

docker build -t springboot-app .

正文到此结束