跳到主要内容

Docker 入门与安装

本篇从零开始。完成后,你将能够:

  • 说清楚镜像、容器和仓库分别是什么;
  • 在 Windows、macOS 或 Ubuntu 上安装 Docker;
  • 运行、查看并删除第一个容器;
  • 看懂一条最基本的 docker run 命令。

1. Docker 解决什么问题

一套应用通常不只有源代码,还依赖运行时、系统工具、第三方库和配置。直接把应用复制到另一台机器时,经常会遇到“我的电脑上能运行,换台机器就不行”。

Docker 的做法是把应用及其运行依赖制作成一个镜像(image)。其他机器拿到同一个镜像后,可以创建出行为基本一致的容器(container)

可以先用下面的类比建立直觉:

Docker 概念类比特点
Dockerfile制作说明书记录镜像如何构建
镜像安装包或只读模板可以复制、分发,不能直接修改
容器按模板启动的应用进程可以启动、停止和删除
仓库(Registry)应用商店用于拉取和推送镜像
卷(Volume)独立数据盘删除容器后仍可保留数据
网络(Network)容器专用局域网让容器互相通信或对外提供服务
容器不是虚拟机

虚拟机通常包含完整的客户操作系统;容器共享宿主机内核,主要隔离进程、网络和文件系统。因此容器通常启动更快、占用更少,但隔离边界也不同于虚拟机。

2. Docker 是怎样工作的

当你执行 docker run nginx 时,大致发生以下过程:

  1. Docker CLI 把请求发送给 Docker Engine;
  2. Engine 检查本地是否有 nginx 镜像;
  3. 如果没有,就从 Docker Hub 拉取镜像;
  4. Engine 基于镜像创建容器,并启动镜像中定义的主进程;
  5. 主进程退出后,容器进入停止状态。

因此,镜像是模板,容器是模板的一次运行实例。同一个镜像可以同时创建多个彼此隔离的容器。

3. 安装前选择版本

个人电脑建议安装 Docker Desktop,它包含 Docker Engine、Docker CLI 和 Compose:

  • Windows 10/11:使用 Docker Desktop,并选择 WSL 2 后端;
  • macOS:根据芯片选择 Apple silicon 或 Intel 安装包;
  • Linux 桌面:可以使用 Docker Desktop,也可以只安装 Docker Engine;
  • Linux 服务器:通常只安装 Docker Engine 和 Compose 插件。

安装包以 Docker 官方安装文档 为准。不要从来源不明的网站下载安装包或一键脚本。

3.1 Windows 安装

  1. 在“启用或关闭 Windows 功能”中启用 WSL 相关功能,或在管理员 PowerShell 中安装 WSL;
  2. 安装 Docker Desktop;
  3. 在 Docker Desktop 设置中确认启用了 Use the WSL 2 based engine
  4. 等待界面显示 Docker Engine 正在运行;
  5. 打开新的 PowerShell 或 Windows Terminal 验证。
# 安装或更新 WSL;执行后如有提示,请重启 Windows
wsl --install

# 查看已安装发行版及其 WSL 版本,VERSION 应为 2
wsl --list --verbose

# 验证 Docker 客户端和服务端是否可以通信
docker version

# 验证 Compose V2 是否可用
docker compose version
在哪里执行命令

本系列的 Linux 风格命令可以在 WSL 终端中执行。PowerShell 对引号、环境变量和路径的处理略有不同,遇到差异时优先使用 WSL。

3.2 macOS 安装

下载并安装 Docker Desktop,启动后等待菜单栏中的 Docker 状态变为运行中,再打开“终端”执行:

# 同时显示 Docker CLI 和 Engine 的版本信息
docker version

# Compose V2 已集成在 docker 命令中,中间有一个空格
docker compose version

3.3 Ubuntu 安装 Docker Engine

下面以 Ubuntu 为例,通过 Docker 官方 APT 仓库安装。每组命令都可以直接复制执行。

# 删除可能冲突的旧包;未安装时不会造成问题
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do
sudo apt-get remove -y "$pkg"
done

# 更新软件索引并安装添加仓库所需工具
sudo apt-get update
sudo apt-get install -y ca-certificates curl

# 创建 APT 密钥目录
sudo install -m 0755 -d /etc/apt/keyrings

# 下载 Docker 官方仓库签名密钥
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

添加与你的 Ubuntu 版本对应的软件仓库:

# 写入 Docker 官方 APT 仓库;命令会自动读取 CPU 架构和系统代号
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装 Engine、CLI、containerd、Buildx 和 Compose 插件
sudo apt-get update
sudo apt-get install -y \
docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

启动服务并验证:

# 立即启动 Docker,并设置为开机自动启动
sudo systemctl enable --now docker

# 确认服务状态;看到 active (running) 表示正常
sudo systemctl status docker --no-pager

# 首次验证可使用 sudo,避免用户权限尚未配置
sudo docker version
sudo docker run --rm hello-world

如果希望当前用户不加 sudo 也能运行 Docker:

# 创建 docker 组(已存在时忽略错误),再把当前用户加入该组
sudo groupadd docker 2>/dev/null || true
sudo usermod -aG docker "$USER"

# 让当前终端临时加载新组;重新登录也能永久生效
newgrp docker

# 确认现在可以不使用 sudo
docker run --rm hello-world
Docker 组等同于高权限

docker 组成员可以挂载宿主机目录或启动高权限容器,实际接近宿主机 root 权限。只把可信用户加入该组。共享服务器应评估 rootless Docker 或受限的 sudo 规则。

其他 Linux 发行版的软件包命令不同,请使用官方文档中对应发行版的安装步骤,不要直接套用 Ubuntu 命令。

4. 运行第一个 Web 容器

现在启动一个 Nginx Web 服务器:

# 后台运行 nginx,并把宿主机 8080 端口映射到容器 80 端口
docker run --detach \
--name beginner-web \
--publish 8080:80 \
nginx:1.27-alpine

第一次运行会看到若干 Pull complete,表示 Docker 正在下载镜像。最后输出的一长串字符是容器 ID。

打开浏览器访问 http://localhost:8080,应该看到 Nginx 欢迎页。没有图形界面的 Linux 服务器可执行:

# 请求本机 8080 端口;响应中应包含 Welcome to nginx
curl http://127.0.0.1:8080

查看正在运行的容器:

# 只显示当前正在运行的容器
docker ps

# 查看 beginner-web 最近 20 行日志
docker logs --tail 20 beginner-web

docker ps 中几个重要字段的含义:

字段含义
CONTAINER ID容器短 ID,可代替名称用于命令参数
IMAGE创建容器所使用的镜像
STATUS容器运行状态和持续时间
PORTS宿主机端口到容器端口的映射
NAMES容器名称,本例为 beginner-web

完成实验后停止并删除容器:

# 先停止容器的主进程
docker stop beginner-web

# 删除已停止的容器;镜像仍保留在本地
docker rm beginner-web

# 确认容器已经不存在;-a 会同时显示停止的容器
docker ps -a

5. 看懂 docker run

刚才的命令可以拆成以下部分:

参数含义
docker run根据镜像创建并启动一个新容器
--detach / -d在后台运行
--name beginner-web为容器指定容易记忆的名称
--publish 8080:80 / -p 8080:80将宿主机 8080 端口转发到容器 80 端口
nginx:1.27-alpine镜像名和标签;标签通常表示版本或变体

注意,docker run 每执行一次都会创建一个新容器。重新启动已有容器使用 docker start,而不是再次执行同样的 docker run

6. 最小日常检查

# 查看客户端和服务端版本;只有 Client 往往说明 Engine 未运行
docker version

# 查看存储驱动、CPU、内存、镜像数量等系统信息
docker info

# 查看镜像、容器、卷和构建缓存分别占用多少空间
docker system df

# 查看本地已有镜像
docker image ls

常见安装问题

现象原因和处理
Cannot connect to the Docker daemonEngine 未启动;启动 Docker Desktop,或在 Linux 执行 sudo systemctl start docker
permission denied ... docker.sock当前用户无权限;暂时使用 sudo,或重新登录使 docker 组生效
port is already allocated8080 已被占用;换成 -p 8081:80
拉取镜像超时检查 DNS、代理和网络策略;不要随意关闭 TLS 校验
Apple silicon 出现平台警告镜像不包含 arm64 版本;优先更换多架构镜像

7. 本篇练习

  1. 把示例中的宿主机端口从 8080 改成 8081,确认新地址可以访问;
  2. 分别执行 docker psdocker ps -a,观察停止容器是否显示;
  3. 删除容器后执行 docker image ls,确认镜像为什么仍然存在;
  4. docker run --help 查找 --rm 参数的作用。

下一篇将使用 Dockerfile 制作自己的第一个镜像,并解释镜像标签、构建上下文和缓存。