Docker 基础回顾:镜像、容器、仓库与常用命令

说实话,很多工程师一上来就急着跑 Isaac Sim,结果连 Docker 的基本概念都没搞清楚。我见过太多人在容器里折腾半天,最后发现是镜像没拉对,或者容器启动参数写错了。这一章,咱们把 Docker 的核心概念和常用命令捋一遍。别嫌基础,这些是后面所有操作的地基。

Docker 三大核心概念

Docker 的体系其实就三个东西:镜像、容器、仓库。搞懂它们的关系,你就能理解 Docker 为什么这么流行。

概念 类比 说明
镜像(Image) ISO 安装盘 / 类模板 只读的、分层打包的文件系统,包含运行环境、依赖、代码
容器(Container) 运行中的虚拟机实例 镜像的运行态,可读写、可启动、可停止、可删除
仓库(Registry) GitHub / 应用商店 存储和分发镜像的地方,Docker Hub 是默认的公共仓库

我个人的理解方式: 镜像就是菜谱,容器就是按菜谱做出来的菜。菜谱可以反复用,菜吃完了可以重新做。仓库就是菜谱分享平台,你从上面下载别人写好的菜谱,也可以上传自己的。

这里有个关键点:镜像是分层的。每一层代表一个 Dockerfile 指令,层与层之间可以复用。我在项目中遇到过,有人把同一个基础镜像拉了三遍,白白浪费了磁盘空间和带宽。其实 Docker 的层缓存机制会自动复用已有的层,只要你没改前面的指令。

常用 Docker 命令速查

命令不用全背,但下面这几个你最好记在脑子里。我平时工作 80% 的时间都在用它们。

镜像操作

# 拉取镜像
docker pull nvidia/cuda:12.2.0-devel-ubuntu22.04

# 列出本地镜像
docker images

# 删除镜像
docker rmi nvidia/cuda:12.2.0-devel-ubuntu22.04

# 构建镜像(从 Dockerfile)
docker build -t my-isaac-sim:latest .

小技巧: 拉取 Isaac Sim 的镜像时,我建议先 docker pull 一个干净的 Ubuntu + CUDA 基础镜像,确认网络没问题,再拉完整的 Isaac Sim 镜像。否则你等半小时发现下载失败,心态会崩。

容器操作

# 创建并启动容器
docker run --gpus all -it --name isaac_container nvcr.io/nvidia/isaac-sim:latest

# 列出运行中的容器
docker ps

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

# 停止容器
docker stop isaac_container

# 启动已停止的容器
docker start isaac_container

# 进入容器内部
docker exec -it isaac_container /bin/bash

# 删除容器
docker rm isaac_container

嗯,这里要注意 docker run 和 docker exec 的区别。前者是创建新容器,后者是进入已有容器。我刚开始用的时候经常搞混,结果每次想进容器都重新创建了一个,搞得系统里一堆孤儿容器。

仓库与日志

# 登录仓库
docker login nvcr.io

# 推送镜像到仓库
docker push my-repo/isaac-sim:custom

# 查看容器日志
docker logs isaac_container

# 实时跟踪日志
docker logs -f isaac_container

Dockerfile 编写入门

Dockerfile 就是构建镜像的脚本。你想想看,如果每次都要手动装依赖、配环境,那跟传统部署有什么区别?Dockerfile 让这一切自动化、可重复。

下面是一个给 Isaac Sim 打基础用的 Dockerfile 示例:

# 使用官方基础镜像
FROM nvidia/cuda:12.2.0-devel-ubuntu22.04

# 设置环境变量,避免交互式安装
ENV DEBIAN_FRONTEND=noninteractive

# 安装系统依赖
RUN apt-get update && apt-get install -y \
    wget \
    git \
    python3-pip \
    libgl1-mesa-glx \
    libegl1-mesa \
    libxrandr2 \
    libxss1 \
    libxcursor1 \
    libxcomposite1 \
    libasound2 \
    libxi6 \
    libxtst6 \
    && rm -rf /var/lib/apt/lists/*

# 安装 Python 依赖
RUN pip3 install --upgrade pip && \
    pip3 install numpy scipy matplotlib

# 创建工作目录
WORKDIR /workspace

# 复制本地文件(如果有)
# COPY ./scripts /workspace/scripts

# 默认命令
CMD ["/bin/bash"]

我曾经踩过的坑: 在 Dockerfile 里写 RUN apt-get update 但不写 apt-get install,或者写了 install 但忘了 rm -rf /var/lib/apt/lists/*。前者会导致缓存过期,后者会让镜像体积膨胀 200MB 以上。记住:update 和 install 要写在同一行,并且清理缓存。

Dockerfile 指令速查表

指令 作用 使用频率
FROM 指定基础镜像 必用
RUN 执行命令(构建时) 高频
COPY / ADD 复制文件到镜像 高频
WORKDIR 设置工作目录 推荐使用
ENV 设置环境变量 高频
EXPOSE 声明容器端口 中频
CMD 默认启动命令 必用
ENTRYPOINT 容器入口点 中频

我的习惯: 尽量用 COPY 而不是 ADD。ADD 会自动解压 tar 包,有时候会带来意想不到的行为。明确的事情用明确的指令,这是工程师的素养。

Docker 核心工作流

下面这张图展示了 Docker 从构建到运行的全流程。我每次给团队新人讲 Docker,都会先画这张图。

Docker 核心工作流 Dockerfile 构建脚本 镜像 (Image) 只读模板 容器 (Container) 运行实例 docker build docker run 仓库 (Registry) 存储 & 分发 docker push docker pull 💡 关键理解: • 镜像 = 类(class),容器 = 实例(instance) • 一个镜像可以启动多个容器,每个容器互不干扰 • 仓库是镜像的「GitHub」,方便团队协作和版本管理

说白了,Docker 就是把你整个运行环境打包成一个「镜像」,然后到处跑。你不需要关心宿主机装了什么库、什么版本,只要 Docker 能跑,你的应用就能跑。这就是为什么 Isaac Sim 这种依赖复杂、对 GPU 驱动有严格要求的软件,用 Docker 部署是最优雅的方式。

总结一下本章的核心:

  • 镜像(Image)是只读模板,容器(Container)是运行实例,仓库(Registry)是镜像市场
  • 掌握 docker pull/run/exec/ps/stop/rm 这六个命令,你就能应付 90% 的日常操作
  • Dockerfile 的关键是 FROM、RUN、COPY、CMD,记住「层缓存」和「清理缓存」两个原则