Skip to content

01 Docker基础入门

在应用开发和部署过程中,环境差异是最常见的问题之一。开发环境中运行正常的AI Agent服务,迁移到其他机器后可能会因为Python版本、系统依赖或环境变量不同而无法启动。

Docker的思路是把应用及其运行所需的环境一起打包成镜像。目标机器安装Docker后,即可按照同一套运行环境启动应用。

一、Docker是什么

Docker是一个开源的应用容器化平台。它最核心的能力可以概括成一句话:把应用和运行环境打包在一起,实现一次构建、到处运行

传统部署通常需要在服务器上安装Python、安装依赖、配置环境变量并上传代码,任何一个环节不一致都可能导致运行失败。Docker则把代码、Python运行时、依赖库和配置文件放进同一个"容器"里,使应用在不同机器上保持一致的运行方式。

1.1 容器和虚拟机的区别

容器和虚拟机经常被放在一起比较,但它们不是一类东西。

对比项虚拟机容器
隔离级别完整的操作系统内核进程级隔离
启动速度分钟级秒级
资源占用大(每个VM独立内核)小(共享宿主机内核)
镜像大小GB级MB级
适合场景需要完整OS隔离应用级别的隔离和部署

虚拟机提供完整的操作系统隔离,容器则提供更轻量的应用级隔离。容器更像标准化的运行单元,便于快速迁移和部署。

1.2 Docker的核心价值

Docker最实用的价值,主要落在这三件事上:

  1. 环境一致性——开发、测试、生产环境尽量保持一致,减少环境差异导致的问题
  2. 快速部署——镜像打包一次,启动通常是秒级的,不用在每台机器上重新安装依赖
  3. 资源高效——容器共享宿主机的操作系统内核,比虚拟机轻得多,同一台服务器能跑更多应用

二、Docker架构

Docker采用客户端-服务端架构。终端中的docker命令负责发送指令,后台的Docker Daemon负责执行具体操作。

┌──────────────────┐
│   Docker Client   │  ← docker 命令
│   (docker CLI)    │
└────────┬─────────┘
         │ REST API

┌──────────────────┐
│  Docker Daemon    │  ← 后台服务,干脏活累活
│  (dockerd)        │
└────────┬─────────┘

    ┌────┴────┐
    ▼         ▼
 镜像       容器
(Images)  (Containers)
  • Docker Client:也就是终端中的docker命令,负责把指令发给Docker Daemon
  • Docker Daemon:常驻后台的守护进程,负责构建镜像、运行容器、管理网络和存储
  • Docker Registry:用来存储和分发镜像的服务,最常见的公共仓库是Docker Hub

Client和Daemon可以在同一台机器上,也可以隔着网络连接到远程Daemon。

三、容器

容器是镜像跑起来之后的实例。一个镜像可以启动多个容器,这些容器彼此隔离,互不干扰。

理解容器时,可以抓住四个特点:

  • 自包含——运行所需的内容都在容器里,不指望宿主机提前装好一堆东西
  • 隔离——容器之间互不影响,一个容器异常退出不会影响其他容器
  • 独立——每个容器都可以单独管理,删除一个容器不会影响其他容器
  • 可移植——在开发机器上能运行的容器,迁移到Linux服务器后也能运行

3.1 第一个容器

装好Docker Desktop之后,可以先跑一个最小的例子:

bash
docker run -d -p 8080:80 docker/welcome-to-docker

这条命令会执行以下操作:

  1. 从Docker Hub拉取docker/welcome-to-docker镜像
  2. 创建一个新容器
  3. 把容器的80端口映射到宿主机的8080端口
  4. 在后台运行(-d

打开浏览器访问http://localhost:8080,可以看到欢迎页面。

3.2 常用容器命令

bash
# 查看正在运行的容器
docker ps

# 查看所有容器(包括已停止的)
docker ps -a

# 停止容器
docker stop <容器ID>

# 启动已停止的容器
docker start <容器ID>

# 删除容器
docker rm <容器ID>

# 进入容器内部
docker exec -it <容器ID> /bin/bash

docker ps的输出里会列出容器ID、使用的镜像、运行状态、端口映射等信息。操作容器时,通常只需要使用容器ID的前几位,不必复制完整ID。

四、镜像

镜像是一个只读模板,包含运行容器需要的所有文件和配置。可以把镜像理解成一张"安装光盘",容器就是从这张光盘启动出来的"系统"。

镜像有两个重要特点:

  1. 不可变——镜像一旦创建就不能修改,只能基于它创建新镜像
  2. 分层存储——镜像由多个层(layer)组成,每一层代表一组文件系统变更

4.1 镜像的分层结构

一个典型的Python应用镜像可能包含以下层:

第5层:复制应用源代码        (几KB)
第4层:安装pip依赖           (几十MB)
第3层:复制requirements.txt  (几百字节)
第2层:安装Python运行时      (几百MB)
第1层:基础Linux系统         (几十MB)

分层的好处是可以复用。比如两个Python应用都基于同样的基础系统和Python运行时,它们就能共享前两层,不需要重复存储。只修改应用代码时,通常只需要重建最上面的几层,不需要从头构建整个镜像。

4.2 镜像操作命令

bash
# 拉取镜像
docker pull python:3.12-alpine

# 查看本地镜像列表
docker images

# 查看镜像的层信息
docker image history <镜像>

# 删除镜像
docker rmi <镜像>

# 给镜像打标签
docker tag <镜像> <新标>

4.3 镜像标签

镜像用标签区分版本。以python:3.12-alpine为例,python是镜像名,3.12-alpine是标签。如果不写标签,Docker默认使用latest

注意:生产环境不要用latest标签。 latest指向的版本可能会变,今天构建用到的latest和三个月后的latest未必是同一个东西。明确写出版本号,构建结果才更可控。

五、仓库

Docker Registry(仓库)负责存储和分发镜像。Docker Hub是最常用的公共仓库,可以类比成镜像世界里的GitHub。

5.1 Docker Hub

Docker Hub上有三类镜像:

类型说明示例
Docker Official Images官方维护,安全可靠pythonnginxredis
Docker Verified Publishers经过Docker认证的商业镜像datadoggitlab
社区镜像任何人可以发布各种第三方镜像

生产环境优先使用官方镜像或Verified Publisher镜像。社区镜像不是不能用,但一定要认真审查来源和内容。

5.2 推送镜像到仓库

bash
# 登录Docker Hub
docker login

# 给镜像打标签(格式:用户名/镜像名:标签)
docker tag my-app:1.0 yourusername/my-app:1.0

# 推送镜像
docker push yourusername/my-app:1.0

团队内部也可以搭建私有仓库来存储内部镜像,本文不展开说明。

六、总结

学Docker,先把这四个概念放稳:

概念是什么类比
容器(Container)镜像的运行实例运行中的程序
镜像(Image)只读的模板安装光盘
仓库(Registry)存储镜像的服务应用商店
Dockerfile构建镜像的脚本安装说明书(下篇讲)

最常用的命令:

命令作用
docker run创建并启动容器
docker ps查看运行中的容器
docker images查看本地镜像
docker pull拉取镜像
docker stop停止容器
docker rm删除容器

这些概念和命令是后续内容的基础。Dockerfile用于通过文本文件定义镜像构建过程,是进一步使用Docker的重要内容。