‹ 返回笔记 Esc·

Docker 问题与修复

GPU 参数报错 安装 NVIDIA Container Toolkit 验证 Docker GPU 是否可用 --- docker-compose 与 docker compose 添加 Docke…

GPU 参数报错

1docker: Error response from daemon: could not select device driver "" with capabilities: [gpu]

安装 NVIDIA Container Toolkit

验证 Docker GPU 是否可用

1docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi

docker-compose 与 docker compose

添加 Docker 官方源(更完整)

1# 移除旧的 Docker
2sudo apt-get remove docker.io docker-doc docker-compose podman-docker containerd runc
3
4# 添加 Docker 官方 GPG 密钥
5sudo apt-get update
6sudo apt-get install ca-certificates curl
7sudo install -m 0755 -d /etc/apt/keyrings
8sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
9sudo chmod a+r /etc/apt/keyrings/docker.asc
10
11# 添加 Docker 官方源
12echo \
13  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
14  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
15  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
16
17# 安装 Docker 和 Compose 插件
18sudo apt-get update
19sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

BuildKit 挂载 amd 架构缓存

ARM Mac 构建 amd64 镜像时,本地 ARM 的 pip 缓存无法直接使用(架构不同)。使用 Docker BuildKit 的缓存挂载,它会自动处理跨平台并缓存对应架构的 wheel。

1# 安装依赖(使用 BuildKit 缓存挂载,自动处理跨平台)
2RUN --mount=type=cache,target=/root/.cache/pip \
3    pip install \
4    --trusted-host mirrors.aliyun.com \
5    -i http://mirrors.aliyun.com/pypi/simple \
6    -r requirements.txt && \
7    rm -rf /tmp/* /var/tmp/*

BuildKit 会:

自动下载 amd64 架构的 wheel 文件

将下载的文件缓存到 BuildKit 的缓存中

下次构建时直接使用缓存的 amd64 wheel 文件

1第一次构建:
2├─ pip 下载包到 /root/.cache/pip
3├─ BuildKit 检测到缓存挂载
4├─ 将缓存保存到 BuildKit 的缓存存储中
5└─ 构建完成
6
7第二次构建(requirements.txt 未变):
8├─ BuildKit 恢复缓存到 /root/.cache/pip
9├─ pip 发现缓存中已有包
10├─ 直接从缓存读取(无需下载)
11└─ 构建速度大幅提升

buildx 不指定 –driver

1# 不指定 driver
2docker buildx create --name mybuilder --use
3
4# 默认使用: docker-container
5docker buildx inspect mybuilder
6# Driver:    docker-container

Docker 命令行开启网络代理

方法 1:通过 systemd 的 drop-in 环境变量设置

假设你用的是 systemd 管理 Docker 服务(常见于 Ubuntu、CentOS 等):

  1. 创建 drop-in 配置目录(如果尚不存在):
1sudo mkdir -p /etc/systemd/system/docker.service.d
  1. 在该目录下新建一个文件,比如 http-proxy.conf,内容类似:
1[Service]
2Environment="HTTP_PROXY=http://你的代理地址:端口"
3Environment="HTTPS_PROXY=http://你的代理地址:端口"
4Environment="NO_PROXY=localhost,127.0.0.1,.你的内部域名"

注意:如果有用户名/密码,要写作 http://user:pass@proxyhost:port(必要时要进行 URL 编码)。

  1. 重载 systemd 并重启 Docker 服务:
1sudo systemctl daemon-reload
2sudo systemctl restart docker
  1. 检查是否生效:
1sudo systemctl show --property=Environment docker
2# 或者
3docker info | grep -i proxy

这样,当你运行 docker pull 时,daemon 就会从它自己的环境中读取这些代理变量,从而使用代理

方法 2:通过 Docker 的 **daemon.json** 配置代理(当版本支持时)

在某些 Docker 版本,可以在 /etc/docker/daemon.json 中添加代理配置:

1{
2  "proxies": {
3    "default": {
4      "http-proxy": "http://你的代理地址:端口",
5      "https-proxy": "http://你的代理地址:端口",
6      "no-proxy": "localhost,127.0.0.1,.你的内部域"
7    }
8  }
9}

修改后需要重启 Docker 服务。注意:有些 Docker 版本或环境(如 Docker Desktop)可能忽略这个设置。


Desktop Windows 集成进 WSL

第一步:确认 Docker Desktop 状态

在 Windows 中:

  1. 启动 Docker Desktop
  2. 等待右下角状态为 Running

第二步:开启 WSL Integration

Docker Desktop → Settings 中:

  1. General
    • 勾选:Use the WSL 2 based engine
  2. Resources → WSL Integration
    • 勾选:Enable integration with my default WSL distro
    • 或者单独勾选:Ubuntu
  3. 点击 Apply & Restart

第三步:重启 WSL(非常关键)

PowerShell(管理员) 中执行:

1wsl --shutdown

然后重新打开 Ubuntu 终端。

第四步:验证 Docker CLI 是否已注入

在 Ubuntu 中执行:

1which docker
2docker version

正常结果应类似:

  • /usr/bin/docker
  • Client 和 Server 信息均能显示

以超管权限进入容器

可以安装软件

1# -u 0 是使用 root 身份进入,不用 root 无法使用 apt 进行安装包
2docker exec -u 0 -it elasticsearch bash
3apt update
4apt install vim

匿名卷和具名卷区别

类型 命令方式 左侧定义 由谁管理 是否可跨容器复用 管理命令支持 常见用途
匿名卷(Anonymous Volume) -v /path/in/container 无,Docker自动生成 Docker ❌ 一般不复用 ✅(docker volume) 临时数据,生命周期随容器
具名卷(Named Volume) -v volume_name:/path/in/container 卷名(自己定义) Docker ✅ 可复用 ✅(docker volume) 数据持久化,多容器共享
绑定挂载(Bind Mount) -v /host/path:/path/in/container 主机目录路径 用户自己 ✅ 可复用 ❌(非 docker volume 管理) 直接访问宿主机文件,如导入导出

1. 创建匿名卷

1docker run -v /app/data my_image
  • Docker 自动创建一个匿名卷,并挂载到容器内的 /app/data。
  • 使用 docker volume ls 可以看到名称类似于 e3f6e1c7a0a6c3a4c6… 的卷。

2. 创建具名卷

1docker run -v mydata:/app/data my_image
  • 明确指定卷名 mydata,方便日后管理与复用。
  • 可使用多个容器挂载同一个具名卷,实现数据共享。

3. 创建绑定挂载(挂载卷)

1docker run -v /home/user/data:/app/data my_image
  • /home/user/data 是主机上的真实目录。
  • 容器内部的 /app/data 映射到主机这个目录。
  • 不受 docker volume 管理。
  • 容器内操作数据 = 实时操作主机上的文件。

重复镜像加载策略

The image redis:6-alpine already exists, renaming the old one with ID 当你尝试加载一个 Docker 镜像时,如果这个镜像的标签(如 redis:6-alpine)已经在本地存在,Docker 会处理冲突:

它会移除旧镜像的标签(“重命名”旧镜像,将其名称清空)。 然后加载新的镜像,并将它分配给同样的标签 redis:6-alpine。 这个过程确保你的标签总是指向最新加载的镜像。旧的镜像在 Docker 中仍然存在,但没有标签来引用它。如果不需要,可以手动删除旧的镜像。


开启代理

Docker Desktop 中设置 Resources - Proxies - Manual proxy configuration 勾选,并填写 HTTP 和 HTTPS 地址


删除不同标签同镜像

1docker rmi registry.cn-shanghai.aliyuncs.com/zailiang/milvus:v2.4.5

容器挂载方式

方式 1:挂载本地目录

1-v $(pwd)/elasticsearch/data:/usr/share/elasticsearch/data
2-v $(pwd)/elasticsearch/plugins:/usr/share/elasticsearch/plugins

这种方式是将主机上的指定目录挂载到容器中。这里 $(pwd)/elasticsearch/data$(pwd)/elasticsearch/plugins 是主机上的实际目录:

优点:可以直接在主机上查看和编辑这些目录中的数据,任何对文件的更改都会立即在容器中生效。

缺点:需要确保主机目录结构的正确性。如果目录不存在,Docker 不会自动创建,可能会导致启动失败。另外,主机系统的文件权限、文件系统类型等因素可能会影响容器的正常运行。

方式 2:使用 Docker 卷

1-v es-data:/usr/share/elasticsearch/data
2-v es-plugins:/usr/share/elasticsearch/plugins

这种方式是将 Docker 卷挂载到容器中,es-dataes-plugins 是 Docker 卷名:

优点:Docker 卷的管理和存储由 Docker 负责,文件安全性和性能通常较好。Docker 卷会跨容器保留数据,适合数据持久化,且不依赖主机文件系统。

缺点:Docker 卷的实际存储路径(如 /var/lib/docker/volumes)在 macOS 和 Windows 主机上通常不可直接访问,因此无法在主机上直接查看和编辑卷内数据。

使用建议

开发调试时:建议使用本地目录挂载方式,方便直接在主机上查看和编辑数据或配置。

生产环境:建议使用Docker 卷方式,以便更好地管理和保护数据,同时避免因主机文件系统问题导致容器运行异常。


容器网络连接解析规则

1docker run -d \
2  --name haha \
3  --net elastic \
4  -p 9200:9200 -p 9300:9300 \
5  elasticsearch:8.8.1

若 elasticsearch 容器运行命名为 haha,则在其同网络的其他容器,例如 logstash 中配置与 elasticsearch 的连接 URL 就为:http://haha:9200


容器目录挂载机制

如果你在 Docker 中使用挂载命令将宿主机的目录 $HOME/logs 挂载到容器中的 /home/zailiang/logs,但容器内的 /home/zailiang/logs 目录不存在,Docker 会如何处理这个情况取决于你指定的挂载方式:

  1. 创建目录
    • 如果宿主机的目录 $HOME/logs 存在且包含文件,Docker 将会把这个目录的内容挂载到容器内的 /home/zailiang/logs
    • 如果容器内的 /home/zailiang/logs 目录不存在,Docker 会在挂载时 自动创建这个目录。因此,容器启动时会创建 /home/zailiang/logs,并将宿主机的内容映射到该目录中。
  2. 如果宿主机的目录不存在
    • 如果你指定的宿主机目录 $HOME/logs 不存在,Docker 将会启动容器,但容器内的 /home/zailiang/logs 将是一个 空目录。此时,任何尝试访问 /home/zailiang/logs 的操作都将得到一个空目录的视图。

–link 与 –network(–net) 的区别

由于 –link 的静态性和缺乏灵活性,在如今以微服务和容器编排为核心的架构中已经不再适用。Docker 自定义网络功能更为灵活、安全和可靠,因此 –link 不再推荐使用。


pull 报错:connection refused

1PS C:\Users\Zailiang> docker pull milvusdb/milvus:v2.5.11
2Error response from daemon: failed to resolve reference "docker.io/milvusdb/milvus:v2.5.11": failed to do request: Head "https://registry-1.docker.io/v2/milvusdb/milvus/manifests/v2.5.11": proxyconnect tcp: dial tcp 127.0.0.1:7897: connect: connection refused

什么都不需要配置!!!Resource - Proxies 信息也不需要填

开启 Docker 前先关闭网络代理,启动完 Docker 方可打开网络代理,此时就正常了。


无权限使用 docker 命令

1permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Head "http://%2Fvar%2Frun%2Fdocker.sock/_ping": dial unix /var/run/docker.sock: connect: permission denied

这个错误是因为当前用户没有权限访问 Docker 守护进程(Docker Daemon)。Docker 默认需要 rootdocker 用户组权限才能操作。以下是解决方法:

方法 1:使用 **sudo**(临时解决)

1sudo docker images

方法 2:将当前用户加入 **docker** 用户组(推荐)

1# 1. 检查 docker 用户组是否存在
2sudo groupadd docker  # 如果不存在则创建
3# 2. 将当前用户加入 docker 组
4sudo usermod -aG docker $USER
5# 3. 重启终端
6# 4. 验证权限
7docker images

# syntax=docker/dockerfile:1 特性

  • BuildKit 已经是默认构建引擎
  • 即使不写 # syntax=...,也会自动使用 BuildKit
  • 大部分新特性已经默认可用

如果你:

  • 使用 Docker 20.10+
  • 只用基础指令 (FROM, RUN, COPY, CMD 等)
  • 不需要 --mount 或 heredoc 等高级特性

可以不写,性能提升已经自动获得

如果你:

  • 需要明确使用高级特性
  • 想确保团队环境一致
  • 追求最佳实践

建议写上,作为明确的声明