Docker 是目前最主流的容器化技术之一,在 AI模型部署、微服务、DevOps 等场景中广泛使用。
本文将系统介绍:
-
Docker 核心概念
-
Docker 安装
-
镜像与容器管理
-
Volume 数据持久化
-
Docker 网络
-
Docker Compose
-
使用 Docker 部署 TEI 模型推理服务
Docker核心概念
Docker 的核心概念主要有三个:
-
镜像(Image)
-
容器(Container)
-
镜像仓库(Registry)
简单理解:
| 概念 | 类比 |
|---|---|
| 镜像 | 安装包 / 模具 |
| 容器 | 运行后的程序 |
| 镜像仓库 | 软件商店 |
Docker 官方镜像仓库:
https://hub.docker.com/
带有 Docker Official Image 标识的是官方维护镜像。
Docker技术原理
Docker 利用 Linux 内核的两个核心机制:
-
Cgroups
-
Namespaces
实现资源限制和进程隔离。
Cgroups(资源限制)
用于限制容器使用的系统资源,例如:
-
CPU
-
内存
-
IO
-
网络带宽
作用:
-
防止某个容器占满服务器资源
-
容器之间互不影响
Namespaces(资源隔离)
用于隔离系统资源视图,例如:
-
PID namespace(进程)
-
NET namespace(网络)
-
MNT namespace(文件系统)
-
UTS namespace(主机名)
-
IPC namespace
-
USER namespace
因此容器内部看到的:
-
进程
-
网络
-
文件系统
都是 独立视图。
容器本质
容器本质是:
运行在宿主机 Linux 内核上的一组受限进程。
因此:
Docker 不是虚拟机。
| 容器 | 虚拟机 |
|---|---|
| 共享宿主机内核 | 独立内核 |
| 启动秒级 | 启动分钟级 |
| 资源占用小 | 资源占用大 |
Docker安装
官方安装入口
https://get.docker.com/
⚠ `get.docker.com `是快速安装脚本
生产环境建议使用官方仓库安装。
Linux安装
curl -fsSL https://get.docker.com -o install-docker.sh
sh install-docker.sh
验证:
docker --version
Windows安装
步骤:
-
打开 启用或关闭 Windows 功能
-
勾选 Virtual machine platform/虚拟机平台 和 适用于Linux的Windos子系统 (WSL)
-
重启电脑
-
设置 WSL2(以管理员身份打开命令提示符)
wsl --set-default-version 2
wsl --update若处于国内网络可以加上 --web-download
下载 Docker Desktop
https://www.docker.com/
若想指定安装目录,在安装文件目录中使用命令行方式,```--installation-dir=path```可指定安装位置
start /w "" "Docker Desktop Installer.exe" install --installation-dir=D:\Docker
安装后测试:
docker --version
Mac安装
只需在官网下载对应的安装包,安装即可运行
Docker镜像
下载镜像
完整格式:
docker pull docker.io/library/nginx:latest
含义:
docker.io registry
library namespace
nginx image
latest tag
简写:
docker pull nginx
指定架构
docker pull --platform=xxx nginx
常见架构:
| 架构 | 说明 |
|---|---|
| amd64 | x86服务器 |
| arm64 | ARM设备 |
镜像加速
修改配置文件:
/etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.m.1panel.live",
"https://hub.rat.dev"
]
}
重启Docker环境:
systemctl restart docker
Desktop配置镜像
Docker Desktop ------> 设置 ------> Docker Engine ------> 添加 配置文件内容的 registry-mirrors 部分的内容 ------> 点击 Apply&restart
Docker容器管理
查看镜像
docker images
删除镜像
docker rmi image_id
清理未使用镜像
docker image prune
Docker运行容器
示例:部署 Huggingface TEI推理服务
docker run -d \
--name tei-cross-MiniLM-gpu2 \
--gpus '"device=2"' \
-p 18981:80 \
-v /home/ghc/ebo_memory_test/models/models--cross-encoder--ms-marco-MiniLM-L-6-v2:/model/cross-encoder--ms-marco-MiniLM-L-6-v2 \
--pull always \
ghcr.io/huggingface/text-embeddings-inference:cuda-latest \
--model-id /model/cross-encoder--ms-marco-MiniLM-L-6-v2 \
--pooling mean \
--dtype float16 \
--max-concurrent-requests 2048 \
--max-batch-tokens 65536 \
--max-batch-requests 4096 \
--max-client-batch-size 64 \
--payload-limit 8000000 \
--tokenization-workers 32
参数解释:
| 参数 | 作用 |
|---|---|
| -d | 后台运行 |
| --name | 容器名称 |
| --gpus | 指定GPU |
| -p | 端口映射 |
| -v | 数据挂载 |
| --pull always | 每次拉取镜像 |
测试模型接口
curl 127.0.0.1:18981/rerank \
-X POST \
-d '{
"query": "什么是深度学习?",
"texts": [
"深度学习是机器学习的一个分支,它利用多层神经网络进行数据分析。",
"深度学习已广泛应用于图像识别、自然语言处理等领域。",
"深度学习使得计算机能够像人类一样进行决策和学习。",
"深度学习的核心思想是通过大量的数据训练神经网络,自动提取特征。",
"随着数据量的增大,深度学习的表现越来越好。"
]
}' \
-H 'Content-Type: application/json'
返回:
{
"results":[...]
}
表示 rerank 推理成功。
后台执行
docker run -d image_name/image_id
-d在后台执行,不会阻塞当前窗口
-it让容器进入控制台进行交互
⚠ 服务型容器通常使用`-d`
端口映射
-p 宿主机port:容器port宿主机端口映射到Docker端口。容器内的网络与宿主机的网络默认是隔离的,需要在启动参数中指定映射
参数传递
-e arg_name=arg
一般在仓库的镜像网址中会列出可以传递的环境变量
容器命名
--name container_name容器名称必须唯一,与容器的ID等价
查看容器
查看正在运行的容器:
docker ps
-a查看所有容器,包括已经停止运行的
停止/启动容器
docker stop/start container_id/container_name
删除容器
docker rm container_id/container_name
-f强制删除,可直接删除正在运行的容器
临时调试容器
-it让容器进入控制台进行交互
--rm让容器停止时自动删除
这对指令一般连用
docker run -it --rm alpine
ls
exit
# alpine轻量级Linux镜像,这里退出后容器自动删除
重启策略
--restart always任何停止(容器内部崩溃/宿主机断电等)都会立即重启
--restart unless-stopped重启因意外原因停止的容器(手动停止后不重启)
Volume(数据持久化)
Docker数据持久化有两种方式:
绑定挂载
-v host_path:container_path
特点:
-
容器删除数据不丢
-
与宿主机同步
命名卷
创建存储空间:
docker volume create volume_name
使用命名卷:
docker run -v volume_name:/data
查看真实路径:
docker volume inspect volume_name
列出所有创建过的命名卷:
docker volume list
删除命名卷:
docker volume rm volume_name
删除所有没有任何容器在使用的卷:
docker volume prune -a
Docker调试命令
查看容器参数
docker inspect container_name
查看日志:
docker logs container_name
-f滚动查看
在容器内部执行Linux命令:
docker exec container_id/container_name linux_command
进入容器:
docker exec -it container_name /bin/bash
Dockerfile
Dockerfile 定义镜像构建过程。
构建镜像
以Python程序为例,使用FastAPI创建一个get接口,运行在8000接口,requirements文件列出了程序的Python的依赖。
运行这个程序需要三步骤:1. 安装Python环境。 2. 安装依赖`pip install -r requirements.txt` 3.启动项目`python main.py`。最后浏览器访问`localhost:8000`
创建Dockerfile文件,所有Dockerfile第一行都是FROM,即该镜像从哪个镜像基础上构建而来。
搜索选择Python官方镜像Explore Docker's Container Image Repository | Docker Hub,选择3.13-slim
# file:Dockerfile
FROM python:3.13-clim
# 类似cd,切换到镜像内的目录作为工作目录
WORKDIR /app
# 先确保环境依赖没有问题
COPY requirements.txt .
# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt
# 将原本的代码文件拷贝到镜像内的工作目录
COPY . .
# 声明镜像提供的服务端口,并不强制,仅作提示
EXPOSE 8000
# 容器运行时的默认启动命令,一个Dockerfile文件里面只能写一个CMD。ENTRYPOINT优先级更高,不容易被覆盖
CMD ["python", "main.py"]
构建好Dockerfile文件后, 在当前目录执行构建镜像:
docker build -t image_name[:version_name] .
同样能在本地基于这个镜像创建容器并运行
docker run -d -p 8000:8000 image_name
推送镜像
用户名即镜像命名空间
本地工作目录中登录Docker:```docker login```打开网址填写验证码,回到本地命令行显示"Login Succeeded"
此时构建镜像必须带上用户名:
docker build -t username/image_name[:version_name] .
docker push username/image_name[:version_name]
推送成功后即可在DockerHub上搜索
容器编排
一个应用往往由前端、后端、数据库等多部分组成。多应用的最佳实践时将每个模块打包成一个独立的容器。但单独配置、执行、管理会很复杂甚至出错,Docker Compose使用yml文件管理多个容器,里面列出容器之间是如何创建、以及如何协同工作的。
针对上述案例对应的Compose的yml文件配置,```depends_on```能指定启动顺序
# docker-compose.yml
services:
my_mongodb:
image: mongo
environment:
MONGO_INITDB_ROOT_USERNAME: name
MONGO_INITDB_ROOT_PASSWORD: pass
volumes:
- /my/datadir:/data/db
my_mongodb_express:
image:mongo-express
ports:
- "8081:8081"
environment:
ME_CONFIG_MONGODB_SERVER: my_mongodb
ME_CONFIG_MONGODB_USERNAME: name
ME_CONFIG_MONGODB_PASSWORD: pass
depends_on:
- my_mongodb
创建并启动Compose:
docker compose up
-d后台运行
-f file_name指定文件名。若不指定文件名,必须是标准文件名```docker-compose.yml```
停止并删除容器:
docker compose down
仅停止容器:
docker compose stop
运行容器:
docker compose start
若compose已经在运行了,重复执行```compose up```并不会启动新的容器,没有任何效果。
Docker网络
查看网络
docker network list
默认模式:
bridge
host
none
删除自定义子网:
docker network rm network_name
Bridge模式
Docker网络默认是桥接模式,所有容器默认连接到这个网络,每个容器都分配了一个内部IP地址。
-
默认子网 172.17开头
-
容器间可通过容器名通信
-
容器网络与宿主机的网络互相隔离
创建网络:
docker network create mynetwork
默认情况下,创建的子网也是桥接模式。
加入网络:运行时使用参数```--network network_name```
指定容器加入不同的子网,同一个子网的不同容器之间可以互相通信,而跨子网则不可以通信。
同一个子网的容器可以使用容器名称互相访问,而不必使用内部IP地址。
Docker子网内部有一个DNS机制,可以把名字转换成IP地址。
同网络容器可直接通过 容器名通信。
示例:创建子网network1;创建容器my_mongodb没有指定宿主机的端口映射;创建容器mongodb客户端my_mongodb_express指定子网,并与宿主机做映射;通过my_mongodb_express作为桥梁,实现了宿主机通过8081端口即可访问到mongodb的my_mongodb内的数据。
docker network create network1
docker run -d \
--name my_mongodb \
-e MONGO_INITDB_ROOT_USERNAME=name \
-e MONGO_INITDB_ROOT_PASSWORD=pass \
-v /my/datadir:/data/db \
--network network1 \
mongo
docker run -d \
--name my_mongodb_express \
-p 8081:8081 \
-e ME_CONFIG_MONGODB_SERVER=my_mongodb \
-e ME_CONFIG_MONGODB_USERNAME=name \
-e ME_CONFIG_MONGODB_PASSWORD=pass \
--network network1 \
mongo-express
Host模式
Docker容器直接共享宿主机的网络,容器直接使用宿主机的IP地址,无需-p参数进行端口映射,容器内的服务直接运行在宿主机的端口上,通过宿主机的IP和端口能直接访问到容器。
docker run -d --network host image_name
没有指定端口映射也能在宿主机直接访问`ip:port`
# 进入容器查看IP地址
docker exec -it container_id/container_name /bin/sh
# 安装网络工具
apt update
apt install iproute2
ip addr show
None模式
docker run --network none nginx
不联网模式