Ubuntu 零基础搭建 Docker 与基础使用笔记
适用对象:第一次接触 Docker 的学生
建议系统:Ubuntu 22.04 LTS、24.04 LTS 或更新的官方支持版本
更新日期:2026 年 7 月 18 日
学习目标:完成 Docker 安装、镜像拉取、容器运行、端口映射、目录挂载、网络、Dockerfile、Compose、代理和国内镜像加速配置。
一、Docker 是什么
1. 用一句话理解 Docker
Docker 是一种"把应用程序和它运行所需要的环境一起打包"的技术。
传统安装软件时,经常会遇到下面的问题:
- 我的电脑可以运行,换一台电脑就不能运行;
- PHP、Java、Python 或数据库版本不一致;
- 缺少依赖包;
- 配置文件路径不一样;
- 软件之间产生冲突;
- 删除软件以后留下大量配置和数据。
Docker 的思路是:
把程序、依赖、运行环境和默认配置放进一个镜像,再用镜像创建容器。
例如,部署 Nginx 时,不需要手动下载源码、安装依赖、编译和修改服务文件,只需要执行:
bash
docker run -d --name my-nginx -p 8080:80 nginx:alpine
Docker 会自动完成:
- 查找本地是否有
nginx:alpine镜像; - 本地没有就从镜像仓库下载;
- 根据镜像创建容器;
- 启动 Nginx;
- 将 Ubuntu 的 8080 端口映射到容器的 80 端口。
二、Docker 与虚拟机的区别
1. 虚拟机
虚拟机通常包含:
- 虚拟硬件;
- 完整操作系统;
- 操作系统内核;
- 应用程序;
- 应用依赖。
优点:
- 隔离程度高;
- 可以运行不同操作系统;
- 适合完整系统实验。
缺点:
- 占用内存和磁盘较大;
- 启动速度较慢;
- 创建和复制成本较高。
2. Docker 容器
Docker 容器通常包含:
- 应用程序;
- 应用依赖;
- 必要的配置文件;
- 必要的用户空间文件。
容器和宿主机共享 Linux 内核,不需要为每个容器启动一套完整内核。
优点:
- 启动快;
- 占用资源较少;
- 方便复制、删除和重新创建;
- 适合快速部署开发环境、数据库、Web 服务和安全靶场。
缺点:
- 容器不是完整虚拟机;
- 容器和宿主机共享内核;
- 错误的权限配置可能带来安全风险;
- 数据如果没有挂载到宿主机或卷中,删除容器后可能丢失。
3. 一个直观类比
- 镜像:软件安装光盘或系统模板;
- 容器:根据模板启动出来的运行实例;
- 镜像仓库:存放镜像的软件下载站;
- Dockerfile:制作镜像的配方;
- Volume:容器使用的持久化硬盘;
- Docker Compose:多个容器的统一启动清单。
三、Docker 的核心组成
1. Docker Client
用户输入的 docker 命令属于 Docker 客户端,例如:
bash
docker ps
docker images
docker run nginx
客户端负责把命令发送给 Docker Engine。
2. Docker Engine
Docker Engine 是真正管理容器的服务,核心后台进程是:
text
dockerd
它负责:
- 下载和管理镜像;
- 创建、启动和删除容器;
- 创建 Docker 网络;
- 管理数据卷;
- 调用 containerd 运行容器。
3. Image:镜像
镜像是只读模板。
例如:
text
ubuntu:24.04
nginx:alpine
mysql:8.4
镜像名称通常由两部分组成:
text
镜像名:标签
例如:
text
nginx:1.28-alpine
其中:
nginx是镜像名;1.28-alpine是标签;- 如果不写标签,Docker 通常使用
latest。
学习和生产环境中尽量写明确版本,不要过度依赖 latest。
4. Container:容器
容器是镜像运行起来以后产生的实例。
同一个镜像可以创建多个容器:
bash
docker run -d --name web1 nginx:alpine
docker run -d --name web2 nginx:alpine
镜像类似"班级统一发放的实验模板",容器类似"每个学生根据模板创建出来的实验环境"。
5. Registry:镜像仓库
镜像仓库用于存储和分发镜像。
常见镜像仓库包括:
- Docker Hub;
- 阿里云容器镜像服务 ACR;
- 腾讯云容器镜像服务;
- 华为云 SWR;
- Harbor 私有镜像仓库;
- 企业自建 Registry。
四、安装前检查 Ubuntu 环境
1. 查看系统版本
bash
cat /etc/os-release
也可以使用:
bash
lsb_release -a
如果提示没有该命令:
bash
sudo apt update
sudo apt install -y lsb-release
2. 查看 CPU 架构
bash
dpkg --print-architecture
常见结果:
amd64:普通 Intel 或 AMD 64 位电脑;arm64:ARM 64 位设备;armhf:ARM 32 位设备。
3. 检查网络
bash
ping -c 4 223.5.5.5
测试 DNS:
bash
ping -c 4 www.baidu.com
测试 HTTPS:
bash
curl -I https://download.docker.com
判断方法:
- IP 能通、域名不通:优先检查 DNS;
- 域名能解析、HTTPS 超时:检查代理、防火墙或网络出口;
- 返回 HTTP 响应头:说明基本网络正常。
4. 检查系统时间
bash
timedatectl
如果时间偏差很大,HTTPS 证书校验可能失败。
启用时间同步:
bash
sudo timedatectl set-ntp true
五、使用 Docker 官方软件源安装 Docker Engine
不建议零基础学生直接使用来源不明的一键安装脚本。
本文采用 Docker 官方 APT 仓库安装。
1. 卸载可能冲突的软件包
bash
sudo apt remove -y \
docker.io \
docker-compose \
docker-compose-v2 \
docker-doc \
podman-docker \
containerd \
runc
如果提示某些软件包没有安装,可以忽略。
注意:
- 这里只是卸载冲突的软件包;
- 原有的
/var/lib/docker数据通常不会自动删除; - 已有重要容器时,不要随意清空该目录。
2. 更新软件包索引
bash
sudo apt update
3. 安装基础工具
bash
sudo apt install -y ca-certificates curl
4. 创建密钥目录
bash
sudo install -m 0755 -d /etc/apt/keyrings
5. 下载 Docker 官方 GPG 密钥
bash
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
设置读取权限:
bash
sudo chmod a+r /etc/apt/keyrings/docker.asc
6. 添加 Docker 官方 APT 软件源
bash
sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
使用代理:
sudo tee /etc/systemd/system/docker.service.d/proxy.conf <<-'EOF'
[Service]
Environment="HTTP_PROXY=http://192.168.146.1:7897"
Environment="HTTPS_PROXY=http://192.168.146.1:7897"
Environment="NO_PROXY=localhost,127.0.0.1"
EOF
重新更新软件包索引:
bash
sudo apt update
检查 Docker 软件包来源:
bash
apt-cache policy docker-ce
正常情况下应该看到来自:
text
download.docker.com
7. 安装 Docker Engine、Buildx 和 Compose
bash
sudo apt install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
各软件包作用:
| 软件包 | 作用 |
|---|---|
docker-ce |
Docker Engine 社区版 |
docker-ce-cli |
Docker 命令行客户端 |
containerd.io |
底层容器运行时 |
docker-buildx-plugin |
新版镜像构建工具 |
docker-compose-plugin |
docker compose 多容器编排工具 |
8. 启动 Docker 并设置开机启动
bash
sudo systemctl enable --now docker
sudo systemctl enable --now containerd
检查服务状态:
bash
sudo systemctl status docker --no-pager
查看是否开机启动:
bash
systemctl is-enabled docker
正常结果:
text
enabled
9. 查看版本
bash
docker --version
sudo docker version
docker compose version
docker buildx version
10. 运行测试容器
bash
sudo docker run --rm hello-world
这条命令会:
- 查找本地
hello-world镜像; - 本地没有则下载;
- 创建一个临时容器;
- 输出测试信息;
- 因为使用了
--rm,运行结束后自动删除容器。
六、让普通用户直接使用 Docker
默认情况下,普通用户执行 Docker 命令可能出现:
text
permission denied while trying to connect to the Docker daemon socket
1. 将当前用户加入 docker 组
bash
sudo usermod -aG docker "$USER"
使新组权限立即生效:
bash
newgrp docker
也可以注销当前用户后重新登录。
2. 测试
bash
docker run --rm hello-world
如果不再需要 sudo,说明配置成功。
3. 安全提醒
docker 组成员通常可以获得接近 root 的系统控制能力。
因此:
- 不要随意把陌生账号加入 docker 组;
- 公共服务器应严格控制 docker 组成员;
- 不要运行来源不明的镜像;
- 不要随意给容器添加
--privileged; - 不要随意挂载
/、/etc、/var/run/docker.sock等敏感路径。
七、理解容器的生命周期
一个容器常见状态:
text
创建 → 运行 → 停止 → 再次启动 → 删除
需要区分:
- 停止容器:容器还存在,只是不运行;
- 删除容器:容器记录和可写层被删除;
- 删除镜像:用于创建容器的模板被删除;
- 删除数据卷:持久化数据可能被永久删除。
八、Docker 最常用命令
1. 查看 Docker 信息
bash
docker info
只查看关键内容:
bash
docker info | grep -E \
'Server Version|Storage Driver|Docker Root Dir|Registry Mirrors|HTTP Proxy|HTTPS Proxy'
查看磁盘占用:
bash
docker system df
2. 镜像管理
搜索镜像
bash
docker search nginx
注意:搜索结果可能包含社区镜像。教学和生产环境应优先使用官方镜像或可信发布者镜像。
拉取镜像
bash
docker pull nginx:alpine
拉取 Ubuntu:
bash
docker pull ubuntu:24.04
查看本地镜像
bash
docker images
等价命令:
bash
docker image ls
查看镜像详细信息
bash
docker image inspect nginx:alpine
删除镜像
bash
docker rmi nginx:alpine
如果镜像正在被容器使用,需要先删除对应容器。
清理没有使用的镜像
bash
docker image prune
不要在不了解影响时使用:
bash
docker system prune -a
-a 可能删除所有没有被现有容器使用的镜像。
3. 容器管理
启动一个交互式 Ubuntu 容器
bash
docker run --rm -it ubuntu:24.04 bash
参数含义:
| 参数 | 含义 |
|---|---|
run |
创建并启动容器 |
--rm |
容器退出后自动删除 |
-i |
保持标准输入打开 |
-t |
分配一个终端 |
ubuntu:24.04 |
使用的镜像 |
bash |
容器启动后执行的命令 |
退出容器:
bash
exit
后台启动 Nginx
bash
docker run -d \
--name my-nginx \
-p 8080:80 \
nginx:alpine
参数含义:
| 参数 | 含义 |
|---|---|
-d |
后台运行 |
--name my-nginx |
设置容器名称 |
-p 8080:80 |
宿主机 8080 映射到容器 80 |
nginx:alpine |
使用 Nginx Alpine 镜像 |
访问:
text
http://Ubuntu服务器IP:8080
在 Ubuntu 本机测试:
bash
curl http://127.0.0.1:8080
查看正在运行的容器
bash
docker ps
查看所有容器
bash
docker ps -a
查看容器日志
bash
docker logs my-nginx
持续查看:
bash
docker logs -f my-nginx
显示最后 50 行:
bash
docker logs --tail 50 my-nginx
进入运行中的容器
bash
docker exec -it my-nginx sh
有些镜像有 Bash:
bash
docker exec -it 容器名 bash
Alpine 镜像通常默认只有 sh,没有 bash。
退出容器终端:
bash
exit
注意:
bash
docker exec -it
只是进入正在运行的容器,不会重新创建容器。
在容器中直接执行命令
bash
docker exec my-nginx nginx -v
查看容器中的进程:
bash
docker top my-nginx
停止容器
bash
docker stop my-nginx
启动已停止容器
bash
docker start my-nginx
重启容器
bash
docker restart my-nginx
删除容器
bash
docker rm my-nginx
强制删除正在运行的容器:
bash
docker rm -f my-nginx
九、端口映射
1. 为什么需要端口映射
容器通常拥有独立的网络空间。
Nginx 在容器内部监听 80 端口,但外部用户不能仅凭容器内部端口直接访问。
需要建立映射:
text
宿主机端口 → 容器端口
例如:
bash
docker run -d -p 8080:80 nginx:alpine
表示:
text
Ubuntu 的 8080 → 容器的 80
2. 端口映射格式
bash
-p 宿主机端口:容器端口
例如:
bash
-p 8080:80
-p 3307:3306
-p 9000:9000
3. 只允许本机访问
bash
docker run -d \
--name local-nginx \
-p 127.0.0.1:8080:80 \
nginx:alpine
这样通常只有 Ubuntu 本机能够通过 127.0.0.1:8080 访问。
4. 安全注意事项
下面的映射:
bash
-p 8080:80
默认可能监听在所有网络接口上,相当于:
bash
-p 0.0.0.0:8080:80
如果服务器有公网地址,服务可能直接暴露到公网。
检查监听端口:
bash
sudo ss -lntp
查看 Docker 端口映射:
bash
docker port my-nginx
十、容器数据为什么会丢失
容器有一个可写层。
在容器内部创建的文件默认保存在容器可写层中:
bash
docker exec -it my-nginx sh
echo "hello" > /tmp/test.txt
exit
停止再启动容器时,文件通常仍然存在。
但是删除容器后:
bash
docker rm -f my-nginx
容器可写层也会被删除。
因此数据库、上传文件、配置文件不能只放在容器可写层中。
常用持久化方式:
- Bind Mount:把宿主机目录挂载到容器;
- Named Volume:让 Docker 管理数据卷。
十一、Bind Mount:目录映射
1. 创建网页目录
bash
mkdir -p ~/docker-lab/html
创建测试页面:
bash
cat > ~/docker-lab/html/index.html <<'EOF'
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>Docker 实验</title>
</head>
<body>
<h1>这是宿主机目录中的网页</h1>
<p>Nginx 正在 Docker 容器中运行。</p>
</body>
</html>
EOF
2. 挂载目录并启动 Nginx
bash
docker run -d \
--name bind-nginx \
-p 8080:80 \
-v "$HOME/docker-lab/html:/usr/share/nginx/html:ro" \
nginx:alpine
参数:
text
-v 宿主机目录:容器目录:权限
其中:
ro:容器只读;rw:容器可读写,默认值。
3. 测试
bash
curl http://127.0.0.1:8080
修改宿主机页面:
bash
echo '<h1>页面已经更新</h1>' > ~/docker-lab/html/index.html
再次访问即可看到变化,不需要重新制作镜像。
4. 使用 --mount 的写法
--mount 更长,但含义更清晰:
bash
docker run -d \
--name mount-nginx \
-p 8081:80 \
--mount type=bind,source="$HOME/docker-lab/html",target=/usr/share/nginx/html,readonly \
nginx:alpine
十二、Named Volume:Docker 数据卷
1. 创建数据卷
bash
docker volume create web-data
2. 查看数据卷
bash
docker volume ls
3. 查看详细信息
bash
docker volume inspect web-data
4. 挂载数据卷
bash
docker run -d \
--name volume-nginx \
-p 8082:80 \
-v web-data:/usr/share/nginx/html \
nginx:alpine
5. 删除容器但保留数据卷
bash
docker rm -f volume-nginx
数据卷仍然存在:
bash
docker volume ls
6. 删除数据卷
bash
docker volume rm web-data
注意:删除数据库数据卷可能造成永久数据丢失。
十三、Docker 网络基础
1. 查看网络
bash
docker network ls
常见网络:
| 网络 | 作用 |
|---|---|
bridge |
普通容器默认网络 |
host |
容器直接使用宿主机网络 |
none |
容器不配置网络 |
2. 创建自定义网络
bash
docker network create lab-net
3. 在网络中启动两个容器
启动 Web 容器:
bash
docker run -d \
--name web \
--network lab-net \
nginx:alpine
启动测试容器,并通过容器名访问 Web 容器:
bash
docker run --rm \
--network lab-net \
busybox \
wget -qO- http://web
这里使用的地址是:
text
http://web
web 是容器名。
自定义 Docker 网络通常能够提供基于容器名的 DNS 解析。
4. 查看容器 IP
bash
docker inspect \
-f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \
web
不要在应用配置中长期依赖动态容器 IP,应优先使用容器名或服务名。
十四、容器自动重启策略
启动服务型容器时常用:
bash
--restart unless-stopped
示例:
bash
docker run -d \
--name nginx-service \
--restart unless-stopped \
-p 8080:80 \
nginx:alpine
常见策略:
| 策略 | 含义 |
|---|---|
no |
不自动重启,默认 |
always |
总是尝试重启 |
unless-stopped |
除非人为停止,否则自动重启 |
on-failure |
进程异常退出时重启 |
修改已有容器:
bash
docker update --restart unless-stopped nginx-service
十五、Dockerfile:制作自己的镜像
1. Dockerfile 是什么
Dockerfile 是一个文本文件,里面写着构建镜像的步骤。
常见指令:
| 指令 | 作用 |
|---|---|
FROM |
指定基础镜像 |
RUN |
构建镜像时执行命令 |
COPY |
把文件复制进镜像 |
WORKDIR |
设置工作目录 |
ENV |
设置环境变量 |
EXPOSE |
声明容器端口 |
CMD |
设置默认启动命令 |
ENTRYPOINT |
设置入口程序 |
2. 创建实验目录
bash
mkdir -p ~/docker-lab/custom-nginx
cd ~/docker-lab/custom-nginx
3. 创建网页
bash
cat > index.html <<'EOF'
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>自定义镜像</title>
</head>
<body>
<h1>这是我自己构建的 Docker 镜像</h1>
</body>
</html>
EOF
4. 创建 Dockerfile
文件名必须是:
text
Dockerfile
创建内容:
bash
cat > Dockerfile <<'EOF'
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
EOF
5. 构建镜像
bash
docker build -t my-nginx:v1 .
命令解释:
| 内容 | 含义 |
|---|---|
docker build |
构建镜像 |
-t my-nginx:v1 |
设置镜像名和标签 |
. |
使用当前目录作为构建上下文 |
6. 查看镜像
bash
docker images my-nginx
7. 启动自定义镜像
bash
docker run -d \
--name custom-nginx \
-p 8083:80 \
my-nginx:v1
测试:
bash
curl http://127.0.0.1:8083
十六、Docker Compose 基础
1. Compose 是什么
单个容器可以使用 docker run。
当一个项目包含多个参数、挂载目录、网络或多个容器时,命令会越来越长。
Docker Compose 使用一个 YAML 文件保存配置,然后统一启动和管理。
新版命令是:
bash
docker compose
不是旧版的:
bash
docker-compose
2. 创建 Compose 实验
bash
mkdir -p ~/docker-lab/compose-nginx/html
cd ~/docker-lab/compose-nginx
创建网页:
bash
cat > html/index.html <<'EOF'
<h1>Docker Compose 启动成功</h1>
EOF
创建 compose.yaml:
bash
cat > compose.yaml <<'EOF'
services:
web:
image: nginx:alpine
container_name: compose-nginx
ports:
- "8084:80"
volumes:
- ./html:/usr/share/nginx/html:ro
restart: unless-stopped
EOF
3. 启动项目
bash
docker compose up -d
4. 查看状态
bash
docker compose ps
5. 查看日志
bash
docker compose logs
持续查看:
bash
docker compose logs -f
6. 停止并删除项目容器和网络
bash
docker compose down
默认不会删除命名数据卷。
删除数据卷:
bash
docker compose down -v
执行 -v 前必须确认数据是否可以删除。
十七、Docker 代理的三个层次
学习 Docker 代理时,必须先区分代理究竟给谁使用。
1. Ubuntu 命令行代理
给下面这些程序使用:
curl;wget;- 部分命令行工具;
- 当前 Shell 中执行的网络程序。
临时设置:
bash
export HTTP_PROXY=http://代理服务器IP:端口
export HTTPS_PROXY=http://代理服务器IP:端口
export NO_PROXY=localhost,127.0.0.1,::1
同时设置小写变量,提高兼容性:
bash
export http_proxy="$HTTP_PROXY"
export https_proxy="$HTTPS_PROXY"
export no_proxy="$NO_PROXY"
测试:
bash
curl -I https://www.google.com
取消:
bash
unset HTTP_PROXY HTTPS_PROXY NO_PROXY
unset http_proxy https_proxy no_proxy
注意:
即使访问目标是 HTTPS,很多 HTTP 代理的地址仍然写成:
text
http://代理IP:端口
这表示客户端先用 HTTP CONNECT 等方式连接代理,不代表最终访问的网站是 HTTP。
2. Docker Daemon 代理
Docker 拉取镜像主要由 Docker 后台服务 dockerd 完成。
只在当前终端执行:
bash
export HTTP_PROXY=...
不一定能让 Docker 后台服务使用代理。
推荐通过 /etc/docker/daemon.json 或 systemd drop-in 为 Docker Daemon 配置代理。
3. 容器和镜像构建代理
容器内部访问互联网、docker build 构建过程中下载依赖,是另外一层代理。
它与 Docker Daemon 拉取镜像不是同一件事。
十八、为 Docker Daemon 设置代理
下面假设代理地址为:
text
http://192.168.1.10:7890
请替换成自己的真实代理地址。
方案一:使用 /etc/docker/daemon.json
Docker 官方文档推荐直接配置 Daemon。
1. 创建目录
bash
sudo mkdir -p /etc/docker
2. 检查是否已有配置
bash
sudo cat /etc/docker/daemon.json
如果文件已经存在,不要直接覆盖,应把新配置合并进原 JSON。
3. 创建配置
bash
sudo tee /etc/docker/daemon.json >/dev/null <<'EOF'
{
"proxies": {
"http-proxy": "http://192.168.1.10:7890",
"https-proxy": "http://192.168.1.10:7890",
"no-proxy": "localhost,127.0.0.1,::1,.local"
}
}
EOF
4. 检查 JSON 语法
安装 jq:
bash
sudo apt install -y jq
检查:
bash
jq . /etc/docker/daemon.json
如果没有报错并能格式化输出,说明 JSON 语法正常。
5. 重启 Docker
bash
sudo systemctl restart docker
6. 验证
bash
docker info | grep -i proxy
测试拉取:
bash
docker pull hello-world
方案二:使用 systemd drop-in
1. 创建目录
bash
sudo mkdir -p /etc/systemd/system/docker.service.d
2. 创建代理配置
bash
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf >/dev/null <<'EOF'
[Service]
Environment="HTTP_PROXY=http://192.168.1.10:7890"
Environment="HTTPS_PROXY=http://192.168.1.10:7890"
Environment="NO_PROXY=localhost,127.0.0.1,::1,.local"
EOF
3. 重新加载 systemd 并重启 Docker
bash
sudo systemctl daemon-reload
sudo systemctl restart docker
4. 查看 Docker 服务环境变量
bash
sudo systemctl show docker \
--property=Environment
5. 测试
bash
docker pull nginx:alpine
代理配置常见错误
错误 1:在虚拟机中填写 127.0.0.1
如果代理软件运行在 Windows,而 Docker 运行在 VMware 中的 Ubuntu:
text
Ubuntu 中的 127.0.0.1 = Ubuntu 自己
它不是 Windows 主机。
正确做法通常是:
- 查看 Windows 在 VMware 虚拟网卡或局域网中的 IP;
- 让代理软件允许局域网连接;
- 在 Ubuntu 中填写 Windows IP;
- 确保 Windows 防火墙允许该端口;
- 从 Ubuntu 测试代理端口是否可达。
测试端口:
bash
nc -vz Windows主机IP 7890
如果没有 nc:
bash
sudo apt install -y netcat-openbsd
错误 2:代理只监听 Windows 的 127.0.0.1
即使 Ubuntu 使用了 Windows IP,代理软件如果只监听:
text
127.0.0.1:7890
虚拟机仍然无法连接。
需要在代理软件中启用类似:
text
Allow LAN
允许局域网连接
监听 0.0.0.0
具体名称取决于代理软件。
错误 3:把 SOCKS5 地址当成 HTTP 代理
例如代理程序提供:
text
SOCKS5:7891
HTTP:7890
Docker Daemon 的 HTTP_PROXY 通常应填写 HTTP 代理端口,而不是直接混用 SOCKS5 端口。
错误 4:修改配置后没有重启 Docker
bash
sudo systemctl restart docker
错误 5:JSON 多写逗号或少写引号
错误示例:
json
{
"registry-mirrors": [
"https://example.com",
]
}
最后一个元素后面不能有多余逗号。
十九、为容器和 Docker Build 设置代理
1. 临时给单个容器设置代理
bash
docker run --rm \
-e HTTP_PROXY=http://192.168.1.10:7890 \
-e HTTPS_PROXY=http://192.168.1.10:7890 \
-e NO_PROXY=localhost,127.0.0.1 \
ubuntu:24.04 \
bash -c 'apt update'
2. 给 Docker Build 传递代理
bash
docker build \
--build-arg HTTP_PROXY=http://192.168.1.10:7890 \
--build-arg HTTPS_PROXY=http://192.168.1.10:7890 \
-t my-image:v1 .
3. 配置当前用户的 Docker Client
创建目录:
bash
mkdir -p ~/.docker
创建配置:
bash
cat > ~/.docker/config.json <<'EOF'
{
"proxies": {
"default": {
"httpProxy": "http://192.168.1.10:7890",
"httpsProxy": "http://192.168.1.10:7890",
"noProxy": "localhost,127.0.0.1,::1,.local"
}
}
}
EOF
这类配置主要用于自动向新容器和构建过程传递代理环境变量。
它不能替代 Docker Daemon 拉取镜像时所需的代理设置。
4. 安全提醒
不要把包含用户名和密码的代理地址写入:
- Dockerfile;
- Git 仓库;
- 公开的 Compose 文件;
- 公共教学资料。
例如不要公开:
text
http://username:password@proxy.example.com:3128
二十、设置国内 Docker 镜像加速
1. 为什么需要镜像加速
执行:
bash
docker pull nginx:alpine
时,Docker 默认可能访问 Docker Hub。
在部分网络环境中可能出现:
- 连接超时;
- TLS 握手超时;
- 下载速度慢;
- 某一层反复重试;
- 无法访问
registry-1.docker.io; - 无法获取认证令牌。
2. 镜像加速不是 APT 软件源
要区分:
Docker APT 软件源
用于安装 Docker 软件本身:
text
docker-ce
docker-ce-cli
containerd.io
Docker Registry Mirror
用于加速拉取:
text
nginx
ubuntu
mysql
redis
二者不是一回事。
3. 配置文件位置
普通 rootful Docker:
text
/etc/docker/daemon.json
4. 通用配置方法
bash
sudo mkdir -p /etc/docker
sudo nano /etc/docker/daemon.json
写入:
json
{
"registry-mirrors": [
"https://你的镜像加速地址"
]
}
重启:
bash
sudo systemctl restart docker
验证:
bash
docker info
在输出中查找:
text
Registry Mirrors
5. 使用阿里云账号专属加速地址
阿里云 ACR 通常会为账号生成专属镜像加速地址。
操作思路:
- 登录阿里云容器镜像服务控制台;
- 进入"镜像工具";
- 打开"镜像加速器";
- 复制账号专属地址;
- 写入
/etc/docker/daemon.json。
示例:
json
{
"registry-mirrors": [
"https://你的账号专属地址.mirror.aliyuncs.com"
]
}
重要提醒:
- 不要复制其他人的专属地址;
- 阿里云官方当前已提示传统 ACR 镜像加速可能停止同步最新镜像;
- 某些镜像或
latest标签可能不是最新版本; - 生产环境不要只依赖单个公共加速器;
- 推荐使用明确版本标签和镜像摘要;
- 重要镜像应同步到自己的私有仓库。
6. 使用 DaoCloud 公共镜像服务
DaoCloud 项目当前提供两类用法。
方法一:为原镜像添加前缀
原镜像:
text
docker.io/library/busybox:latest
改写为:
text
m.daocloud.io/docker.io/library/busybox:latest
拉取示例:
bash
docker pull m.daocloud.io/docker.io/library/busybox:latest
项目说明更推荐这种明确添加前缀的方式。
方法二:配置为 Docker Hub Mirror
/etc/docker/daemon.json:
json
{
"registry-mirrors": [
"https://docker.m.daocloud.io"
]
}
重启:
bash
sudo systemctl restart docker
验证:
bash
docker info | sed -n '/Registry Mirrors/,+5p'
注意:
- 公共服务可能拥堵、限流或临时不可用;
- 缓存可能存在同步延迟;
- 建议使用具体版本标签;
- 不要把用于其他仓库的地址错误配置成 Docker Hub 的 mirror;
- 教学环境可作为临时方案,生产环境应准备自有仓库或稳定出口。
7. 同时配置多个镜像加速地址
json
{
"registry-mirrors": [
"https://账号专属镜像地址",
"https://docker.m.daocloud.io"
]
}
但要注意:
- 地址越多不代表一定越快;
- 某个镜像源返回旧标签时,可能造成版本判断混乱;
- 应优先使用自己可信和可控的镜像服务。
8. 同时配置代理和镜像加速
如果 /etc/docker/daemon.json 已经有镜像配置,不能重新创建另一个同名文件。
应合并成一个 JSON:
json
{
"registry-mirrors": [
"https://你的镜像加速地址"
],
"proxies": {
"http-proxy": "http://192.168.1.10:7890",
"https-proxy": "http://192.168.1.10:7890",
"no-proxy": "localhost,127.0.0.1,::1,.local"
}
}
检查:
bash
jq . /etc/docker/daemon.json
重启:
bash
sudo systemctl restart docker
二十一、镜像仓库的基本使用
镜像加速器只是帮助拉取镜像。
镜像仓库还可以存放自己的镜像。
通用流程:
text
登录仓库 → 给镜像重新打标签 → 推送 → 其他主机拉取
1. 登录仓库
bash
docker login registry.example.com
建议使用访问凭据或令牌,不要在命令行直接写明文密码。
可以使用:
bash
echo "$REGISTRY_PASSWORD" | \
docker login registry.example.com \
-u "$REGISTRY_USER" \
--password-stdin
2. 给镜像重新打标签
本地镜像:
text
my-nginx:v1
仓库地址:
text
registry.example.com/student/my-nginx:v1
执行:
bash
docker tag \
my-nginx:v1 \
registry.example.com/student/my-nginx:v1
3. 推送镜像
bash
docker push registry.example.com/student/my-nginx:v1
4. 拉取镜像
bash
docker pull registry.example.com/student/my-nginx:v1
5. 退出登录
bash
docker logout registry.example.com
二十二、Docker 常见故障排查
1. Docker 服务启动失败
查看状态:
bash
sudo systemctl status docker --no-pager -l
查看日志:
bash
sudo journalctl -u docker -n 100 --no-pager
实时查看:
bash
sudo journalctl -u docker -f
常见原因:
/etc/docker/daemon.jsonJSON 语法错误;- 同一个参数同时在 systemd 启动参数和 daemon.json 中重复配置;
- 存储空间不足;
- iptables 或 nftables 配置冲突;
- containerd 启动失败;
- 代理配置格式错误;
- 镜像地址缺少协议或引号。
2. 检查 daemon.json
bash
sudo cat /etc/docker/daemon.json
jq . /etc/docker/daemon.json
让 Docker 验证配置文件:
bash
sudo dockerd --validate \
--config-file=/etc/docker/daemon.json
3. 拉取镜像超时
错误可能包括:
text
i/o timeout
TLS handshake timeout
context deadline exceeded
Client.Timeout exceeded
排查顺序:
第一步:检查 DNS
bash
getent hosts registry-1.docker.io
第二步:检查 HTTPS
bash
curl -I https://registry-1.docker.io/v2/
返回:
text
401 Unauthorized
通常不代表网络失败,反而说明已经连接到 Registry,只是没有提供认证信息。
第三步:检查 Docker 代理
bash
docker info | grep -i proxy
第四步:检查 systemd 环境
bash
sudo systemctl show docker \
--property=Environment
第五步:检查镜像加速
bash
docker info | sed -n '/Registry Mirrors/,+5p'
第六步:查看服务日志
bash
sudo journalctl -u docker -n 100 --no-pager
4. 权限不足
错误:
text
permission denied while trying to connect to the Docker daemon socket
解决:
bash
sudo usermod -aG docker "$USER"
newgrp docker
查看套接字权限:
bash
ls -l /var/run/docker.sock
5. 容器名称冲突
错误:
text
Conflict. The container name is already in use.
查看:
bash
docker ps -a
删除旧容器:
bash
docker rm -f 容器名
或者换一个名称。
6. 端口被占用
错误:
text
port is already allocated
address already in use
查看端口:
bash
sudo ss -lntp | grep ':8080'
查看 Docker 容器端口:
bash
docker ps --format \
'table {{.Names}}\t{{.Ports}}'
解决方式:
- 停止占用端口的服务;
- 删除旧容器;
- 修改宿主机端口。
例如改成:
bash
-p 8081:80
7. 容器启动后立即退出
查看状态:
bash
docker ps -a
查看日志:
bash
docker logs 容器名
查看退出码:
bash
docker inspect \
-f '{{.State.ExitCode}}' \
容器名
常见原因:
- 容器主进程执行完毕;
- 启动命令写错;
- 配置文件错误;
- 数据库环境变量缺失;
- 权限不足;
- 端口或文件冲突。
容器依赖前台主进程存活。主进程退出,容器就会停止。
8. 磁盘空间不足
查看系统磁盘:
bash
df -h
查看 Docker 占用:
bash
docker system df
查看 Docker 根目录:
bash
docker info | grep 'Docker Root Dir'
谨慎清理停止的容器:
bash
docker container prune
清理悬空镜像:
bash
docker image prune
清理未使用网络:
bash
docker network prune
清理未使用数据卷前必须确认:
bash
docker volume prune
数据库数据经常保存在数据卷中,误删可能无法恢复。
二十三、Docker 安全入门注意事项
1. 不要随意使用 --privileged
bash
docker run --privileged ...
该参数会给容器非常高的系统权限。
普通 Web 服务、数据库和课堂实验通常不需要。
2. 不要随意挂载 Docker Socket
危险示例:
bash
-v /var/run/docker.sock:/var/run/docker.sock
能够访问 Docker Socket 的容器,通常可以控制宿主机上的其他容器,并可能进一步控制宿主机。
3. 不要直接暴露数据库端口到公网
不推荐:
bash
-p 3306:3306
更安全的本机测试方式:
bash
-p 127.0.0.1:3307:3306
4. 使用明确版本
不推荐长期使用:
text
mysql:latest
nginx:latest
ubuntu:latest
推荐:
text
ubuntu:24.04
nginx:1.28-alpine
版本升级应经过测试。
5. 不要把密码直接写进 Dockerfile
错误示例:
dockerfile
ENV MYSQL_PASSWORD=123456
镜像历史或配置中可能暴露密码。
6. 定期查看镜像来源
bash
docker image inspect 镜像名
优先选择:
- Docker Official Image;
- Verified Publisher;
- 企业自己的可信仓库;
- 有明确维护者和版本说明的镜像。
二十四、课堂综合实验
实验目标
完成以下任务:
- 安装 Docker;
- 配置普通用户权限;
- 配置镜像加速或代理;
- 拉取 Nginx;
- 运行 Nginx 容器;
- 使用目录挂载修改网页;
- 查看日志;
- 进入容器;
- 使用 Dockerfile 构建自定义镜像;
- 使用 Docker Compose 启动服务。
实验步骤
1. 验证 Docker
bash
docker version
docker compose version
docker run --rm hello-world
2. 启动 Nginx
bash
docker run -d \
--name student-nginx \
-p 8080:80 \
--restart unless-stopped \
nginx:alpine
3. 查看状态
bash
docker ps
4. 访问服务
bash
curl http://127.0.0.1:8080
5. 查看日志
bash
docker logs student-nginx
6. 进入容器
bash
docker exec -it student-nginx sh
7. 退出容器
bash
exit
8. 删除容器
bash
docker rm -f student-nginx
9. 使用 Bind Mount 重新创建
bash
mkdir -p ~/student-web
echo '<h1>Hello Docker</h1>' \
> ~/student-web/index.html
bash
docker run -d \
--name student-nginx \
-p 8080:80 \
-v "$HOME/student-web:/usr/share/nginx/html:ro" \
nginx:alpine
10. 修改网页并观察变化
bash
echo '<h1>Docker 目录挂载成功</h1>' \
> ~/student-web/index.html
bash
curl http://127.0.0.1:8080
二十五、Docker 命令速查表
服务管理
bash
sudo systemctl start docker
sudo systemctl stop docker
sudo systemctl restart docker
sudo systemctl status docker
sudo systemctl enable docker
镜像管理
bash
docker pull 镜像:标签
docker images
docker image inspect 镜像
docker rmi 镜像
docker image prune
容器管理
bash
docker run 镜像
docker ps
docker ps -a
docker start 容器
docker stop 容器
docker restart 容器
docker rm 容器
docker rm -f 容器
docker logs 容器
docker exec -it 容器 sh
docker inspect 容器
网络管理
bash
docker network ls
docker network create 网络名
docker network inspect 网络名
docker network connect 网络名 容器名
docker network disconnect 网络名 容器名
docker network rm 网络名
数据卷管理
bash
docker volume ls
docker volume create 卷名
docker volume inspect 卷名
docker volume rm 卷名
docker volume prune
Compose
bash
docker compose up -d
docker compose ps
docker compose logs -f
docker compose restart
docker compose stop
docker compose down
docker compose down -v
清理
bash
docker system df
docker container prune
docker image prune
docker network prune
docker volume prune
二十六、初学者必须记住的十句话
- 镜像是模板,容器是镜像运行后的实例。
docker run通常会创建一个新容器,不只是启动旧容器。docker start用于启动已经存在但处于停止状态的容器。- 删除容器不等于删除镜像。
- 数据库数据必须使用目录挂载或数据卷持久化。
-p 8080:80左边是宿主机端口,右边是容器端口。-v 宿主机目录:容器目录用于挂载目录。- Docker 拉取镜像的代理主要要配置给 Docker Daemon。
- 虚拟机中的
127.0.0.1不是 Windows 宿主机。 - 公共镜像加速地址可能限流、过期或同步滞后,生产环境应使用可信私有仓库。
二十七、参考依据
本文安装、代理、镜像加速和基础概念主要依据以下官方或项目维护方资料整理:
- Docker 官方文档:Install Docker Engine on Ubuntu;
- Docker 官方文档:Linux post-installation steps for Docker Engine;
- Docker 官方文档:Daemon proxy configuration;
- Docker 官方文档:Use a proxy server with the Docker CLI;
- Docker 官方文档:Mirror the Docker Hub library;
- Docker 官方文档:Docker Glossary;
- Docker 官方文档:Port publishing and mapping;
- Docker 官方文档:Dockerfile reference;
- 阿里云 ACR 官方文档:官方镜像加速;
- DaoCloud
public-image-mirror项目说明。
国内镜像服务策略、限流和同步状态可能随时调整。教学前应重新检查服务提供方公告,不要长期把某个公共地址视为永久可用。